summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2021-02-16 11:07:46 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2021-02-16 11:07:46 -0500
commitfcb74112105e45ffc0a26aca7d952e84b05c782c (patch)
tree2696401189b65229c4a5f64f9b98d0e276cb277e
parentacfbdf2359f533f88e284b5f5219b5c671992fc7 (diff)
got WNOHANG to work
-rw-r--r--main.c17
-rw-r--r--process-posix.c88
-rw-r--r--process.h4
3 files changed, 41 insertions, 68 deletions
diff --git a/main.c b/main.c
index 8c6308b..d879cb7 100644
--- a/main.c
+++ b/main.c
@@ -146,14 +146,13 @@ int main(int argc, char **argv) {
#endif
setlocale(LC_ALL, ""); // allow unicode
- process_init();
+ char *program = "/usr/bin/sleep";
+ char *args[] = {program, "5", NULL};
+ Process process = {0}, *proc = &process;
- char *program = "/usr/bin/make";
- char *args[] = {program, NULL};
- Process *process = process_exec(program, args);
- if (!process) {
- printf("Error: %s\n", process_geterr());
+ if (!process_exec(proc, program, args)) {
+ printf("Error: %s\n", process_geterr(proc));
return EXIT_FAILURE;
}
#if 1
@@ -161,9 +160,9 @@ int main(int argc, char **argv) {
i64 bytes = 0;
char buf[256];
while (1) {
- bytes = process_read(process, buf, sizeof buf);
+ bytes = process_read(proc, buf, sizeof buf);
if (bytes == -2) {
- printf("Error: %s\n", process_geterr());
+ printf("Error: %s\n", process_geterr(proc));
} else if (bytes == -1) {
usleep(1000);
} else if (bytes == 0) {
@@ -176,7 +175,7 @@ int main(int argc, char **argv) {
{
char message[256];
while (1) {
- int status = process_check_status(process, message, sizeof message);
+ int status = process_check_status(proc, message, sizeof message);
if (status == -1) {
printf("%s!!!\n",message);
break;
diff --git a/process-posix.c b/process-posix.c
index 53363b6..d683abe 100644
--- a/process-posix.c
+++ b/process-posix.c
@@ -6,40 +6,11 @@
struct Process {
pid_t pid;
int pipe;
- bool stopped;
- int exit_status; // INT_MAX if process was terminated
+ char error[64];
};
-static char process_error[64];
-static Process *processes;
-
-static void process_sigaction_sigchld(int signal, siginfo_t *info, void *context) {
- (void)context;
- if (signal == SIGCHLD) {
- pid_t pid = info->si_pid;
- arr_foreach_ptr(processes, Process, process) {
- if (process->pid == pid) {
- process->stopped = true;
- if (info->si_code == CLD_EXITED)
- process->exit_status = info->si_status;
- else
- process->exit_status = INT_MAX;
- }
- }
- }
-}
-
-void process_init(void) {
- struct sigaction act = {0};
- act.sa_sigaction = process_sigaction_sigchld;
- act.sa_flags = SA_SIGINFO | SA_NOCLDSTOP;
- sigaction(SIGCHLD, &act, NULL);
-}
-
-
-
-Process *process_exec(char const *program, char **argv) {
- Process *proc = NULL;
+bool process_exec(Process *proc, char const *program, char **argv) {
+ bool success = false;
int pipefd[2];
if (pipe(pipefd) == 0) {
@@ -56,21 +27,21 @@ Process *process_exec(char const *program, char **argv) {
exit(127);
}
} else if (pid > 0) {
- proc = arr_addp(processes);
// parent process
close(pipefd[1]);
fcntl(pipefd[0], F_SETFL, fcntl(pipefd[0], F_GETFL) | O_NONBLOCK); // set pipe to non-blocking
proc->pid = pid;
proc->pipe = pipefd[0];
+ success = true;
}
} else {
- strbuf_printf(process_error, "%s", strerror(errno));
+ strbuf_printf(proc->error, "%s", strerror(errno));
}
- return proc;
+ return success;
}
-char const *process_geterr(void) {
- return *process_error ? process_error : NULL;
+char const *process_geterr(Process *p) {
+ return p->error;
}
long long process_read(Process *proc, char *data, size_t size) {
@@ -81,7 +52,7 @@ long long process_read(Process *proc, char *data, size_t size) {
} else if (errno == EAGAIN) {
return -1;
} else {
- strbuf_printf(process_error, "%s", strerror(errno));
+ strbuf_printf(proc->error, "%s", strerror(errno));
return -2;
}
@@ -89,31 +60,34 @@ long long process_read(Process *proc, char *data, size_t size) {
void process_stop(Process *proc) {
kill(proc->pid, SIGKILL);
- // get rid of zombie process
- waitpid(proc->pid, NULL, 0);
close(proc->pipe);
- for (u32 i = 0; i < arr_len(processes); ++i)
- if (processes[i].pid == proc->pid)
- arr_remove(processes, i);
+ proc->pid = 0;
+ proc->pipe = 0;
}
-#include <sys/resource.h>
-int process_check_status(Process *proc, char *message, size_t message_size) {
- if (proc->stopped) {
- int status = proc->exit_status;
- process_stop(proc);
- switch (status) {
- case 0:
- if (message) str_printf(message, message_size, "exited successfully");
- return +1;
- case INT_MAX:
- if (message) str_printf(message, message_size, "terminated by a signal");
- return -1;
- default:
- if (message) str_printf(message, message_size, "exited with code %d", status);
+int process_check_status(Process *proc, char *message, size_t message_size) {
+ int wait_status = 0;
+ if (waitpid(proc->pid, &wait_status, WNOHANG) >= 0) {
+ if (WIFEXITED(wait_status)) {
+ int code = WEXITSTATUS(wait_status);
+ if (code == 0) {
+ str_printf(message, message_size, "exited successfully");
+ return +1;
+ } else {
+ str_printf(message, message_size, "exited with code %d", code);
+ return -1;
+ }
+ } else if (WIFSIGNALED(wait_status)) {
+ str_printf(message, message_size, "terminated by signal %d", WTERMSIG(wait_status));
return -1;
}
+ return 0;
+ } else if (errno == ECHILD) {
+ // this process is gone or something?
+ str_printf(message, message_size, "process ended unexpectedly");
+ return -1;
} else {
+ // probably shouldn't happen
return 0;
}
}
diff --git a/process.h b/process.h
index 2b34120..a21fd5b 100644
--- a/process.h
+++ b/process.h
@@ -5,9 +5,9 @@
typedef struct Process Process;
// returns NULL on failure
-Process *process_exec(char const *program, char **argv);
+bool process_exec(Process *process, char const *program, char **argv);
// returns the error last error produced, or NULL if there was no error.
-char const *process_geterr(void);
+char const *process_geterr(Process *process);
// returns:
// -2 on error
// -1 if no data is available right now