Criterion/src/process.c

71 lines
1.6 KiB
C

#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/signal.h>
#include <sys/wait.h>
#include <csptr/smart_ptr.h>
#include "criterion/criterion.h"
#include "process.h"
#include "event.h"
struct process {
pid_t pid;
int in;
};
static pid_t g_runner_pid;
void set_runner_pid(void) {
g_runner_pid = getpid();
}
bool is_runner(void) {
return g_runner_pid == getpid();
}
static void close_process(void *ptr, UNUSED void *meta) {
close(((struct process *) ptr)->in);
}
struct event *worker_read_event(struct process *proc) {
return read_event(proc->in);
}
struct process *spawn_test_worker(struct criterion_test *test, void (*func)(struct criterion_test *)) {
int fds[2];
if (pipe(fds) == -1)
abort();
pid_t pid = fork();
if (pid == -1) {
return NULL;
} else if (!pid) {
close(STDIN_FILENO);
close(fds[0]);
EVENT_PIPE = fds[1];
func(test);
close(fds[1]);
if (!strcmp("1", getenv("CRITERION_NO_EARLY_EXIT") ?: "0"))
return NULL;
else
_exit(0);
}
close(fds[1]);
return unique_ptr(struct process, ({ .pid = pid, .in = fds[0] }), close_process);
}
struct process_status wait_proc(struct process *proc) {
int status;
waitpid(proc->pid, &status, 0);
if (WIFEXITED(status))
return (struct process_status) { .kind = EXIT_STATUS, .status = WEXITSTATUS(status) };
if (WIFSIGNALED(status))
return (struct process_status) { .kind = SIGNAL, .status = WTERMSIG(status) };
return (struct process_status) { .kind = STOPPED };
}