diff options
author | Stefan Zabka <zabkaste@hu-berlin.de> | 2020-06-10 17:11:44 +0200 |
---|---|---|
committer | Stefan Zabka <zabkaste@hu-berlin.de> | 2020-06-10 17:11:44 +0200 |
commit | 5598f8300b9d3e7b49a4d3e65d1d837616b8beb5 (patch) | |
tree | 84fe96600f41f7d9a7b806edf8f27a3fbb82da4e /03_exercise/srv/builtins.c | |
parent | 47aaae2c42d554963fb811b68fdf28c9743598e8 (diff) | |
parent | d80bb89ceaee252cff304c3f7dcb160d3bee8fde (diff) | |
download | betriebssysteme-5598f8300b9d3e7b49a4d3e65d1d837616b8beb5.tar.gz betriebssysteme-5598f8300b9d3e7b49a4d3e65d1d837616b8beb5.zip |
Merge branch 'master' into threadpool
Diffstat (limited to '03_exercise/srv/builtins.c')
-rw-r--r-- | 03_exercise/srv/builtins.c | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/03_exercise/srv/builtins.c b/03_exercise/srv/builtins.c new file mode 100644 index 0000000..f5497a3 --- /dev/null +++ b/03_exercise/srv/builtins.c @@ -0,0 +1,120 @@ +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <wait.h> +#include <stdlib.h> + + +#include "array.h" +#include "builtins.h" + +void handle(int sig) { + /* Do nothing. */ +} + +typedef struct { + pid_t pid; + bool done; +} hack_struct; + +void builtin_wait(process p, bool bind) { + struct sigaction handler; + handler.sa_handler = handle; + sigemptyset(&handler.sa_mask); + handler.sa_flags = 0; + + hack_struct *pcs; + arrayInit(pcs); + + size_t i = 1; + bool error = false; + while (!error && p.argv[i] != NULL) { + char *end; + hack_struct pc; + pc.pid = strtol(p.argv[i], &end, 10); + pc.done = false; + if (*end != '\0') { + fprintf(stderr, "Not a valid pid: %s\n", p.argv[i]); + error = true; + break; + } + arrayPush(pcs) = pc; + ++i; + } + + if (error || arrayLen(pcs) == 0) { + printf("plz giv pid\n"); + arrayRelease(pcs); + return; + } + + int options = WUNTRACED; + if (!bind) { + options |= WNOHANG; + } + + int done_count = 0; + while (done_count != arrayLen(pcs)) { + for (int j = 0; j < arrayLen(pcs); ++j) { + int status; + hack_struct *current_pc = &j[pcs]; + if (current_pc->done) { + continue; + } + + if (bind) { + printf("Resuming %ld...\n", (long) current_pc->pid); + }/* else { + printf("Waiting for %ld...\n", (long) current_pc->pid); + }*/ + // install signal handler without SA_RESTART, so waitpid gets interrupted + sigaction(SIGINT, &handler, NULL); + pid_t res; + if ((res = waitpid(current_pc->pid, &status, options)) < 0) { + if (EINTR == errno) { + // cancelled by ctrl-c + if (bind) { + current_pc->done = true; + ++done_count; + kill(current_pc->pid, SIGKILL); + waitpid(current_pc->pid, &status, options); + printf("Killed [%ld]\n", (long) current_pc->pid); + } else { + kill(current_pc->pid, SIGCONT); + } + } else { + perror("Could not wait for process"); + ++done_count; + current_pc->done = true; + } + } else if (res == 0) { + // wait terminated because nohang + } else { + current_pc->done = true; + ++done_count; + if (bind) { + printf("[%i] ", WEXITSTATUS(status)); + } else { + printf("[%i] TERMINATED\n", current_pc->pid); + if (WIFEXITED(status)) { + printf("[%i] exited normally with status: %i\n", current_pc->pid, + WEXITSTATUS(status)); + } else if (WIFSTOPPED(status)) { + printf("[%i] was stopped by signal: %s\n", current_pc->pid, + strsignal(WSTOPSIG(status))); + } else if (WIFSIGNALED(status)) { + printf("[%i] was terminated by signal: %s\n", current_pc->pid, + strsignal(WTERMSIG(status))); + } else { + printf("[%i] exited (not sure why), exit status: %i\n", current_pc->pid, + WEXITSTATUS(status)); + } + } + } + signal(SIGINT, SIG_IGN); + } + } + + arrayRelease(pcs); +} |