#include <dispatch/dispatch.h>
#include <assert.h>
#include <spawn.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <mach/clock_types.h>
#include "dispatch_test.h"
extern char **environ;
int
main(int argc, char *argv[])
{
dispatch_source_t tmp_ds;
int res;
pid_t pid;
if (argc < 2) {
fprintf(stderr, "usage: harness [...]\n");
exit(1);
}
posix_spawnattr_t attr;
res = posix_spawnattr_init(&attr);
assert(res == 0);
res = posix_spawnattr_setflags(&attr, POSIX_SPAWN_START_SUSPENDED);
assert(res == 0);
int i;
char** newargv = calloc(argc, sizeof(void*));
for (i = 1; i < argc; ++i) {
newargv[i-1] = argv[i];
}
newargv[i-1] = NULL;
res = posix_spawnp(&pid, newargv[0], NULL, &attr, newargv, environ);
if (res) {
errno = res;
perror(newargv[0]);
exit(EXIT_FAILURE);
}
assert(pid > 0);
dispatch_queue_t main_q = dispatch_get_main_queue();
tmp_ds = dispatch_source_proc_create(pid, DISPATCH_PROC_EXIT, NULL, main_q,
^(dispatch_event_t ev __attribute__((unused))) {
int status;
int res2 = waitpid(pid, &status, 0);
assert(res2 != -1);
test_long("Process exited", WEXITSTATUS(status) | WTERMSIG(status), 0);
exit(0);
});
assert(tmp_ds);
uint64_t timeout = 30LL * NSEC_PER_SEC;
tmp_ds = dispatch_source_timer_create(DISPATCH_TIMER_ONESHOT, timeout, 0, NULL, main_q,
^(dispatch_event_t ev __attribute__((unused))) {
kill(pid, SIGKILL);
fprintf(stderr, "Terminating unresponsive process (%0.1lfs)\n", (double)timeout/NSEC_PER_SEC);
});
assert(tmp_ds);
signal(SIGINT, SIG_IGN);
tmp_ds = dispatch_source_signal_create(SIGINT, NULL, main_q,
^(dispatch_event_t ev __attribute__((unused))) {
fprintf(stderr, "Terminating process due to signal\n");
kill(pid, SIGKILL);
});
assert(tmp_ds);
kill(pid, SIGCONT);
dispatch_main();
return 0;
}