From 75b9e7dae24dbba64920659ded6ae4a018dc2943 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 17 Sep 2015 04:07:43 +0200 Subject: [PATCH 1/4] Changed the worker waiting code to be event-driven --- src/compat/pipe.c | 26 +++++-- src/compat/pipe.h | 10 ++- src/compat/process.c | 50 ++++++++++-- src/compat/process.h | 10 ++- src/core/runner.c | 176 +++++++++++++++++++++++++------------------ src/core/runner.h | 3 + src/core/worker.c | 29 ++++--- src/core/worker.h | 11 ++- src/io/event.c | 15 ++++ src/io/event.h | 4 + 10 files changed, 227 insertions(+), 107 deletions(-) diff --git a/src/compat/pipe.c b/src/compat/pipe.c index 0a7e4e9..39167d9 100644 --- a/src/compat/pipe.c +++ b/src/compat/pipe.c @@ -27,18 +27,23 @@ #include "criterion/assert.h" #include "pipe-internal.h" -FILE *pipe_in(s_pipe_handle *p, int do_close) { +FILE *pipe_in(s_pipe_handle *p, enum pipe_opt opts) { #ifdef VANILLA_WIN32 - if (do_close) + if (opts & PIPE_CLOSE) CloseHandle(p->fhs[1]); int fd = _open_osfhandle((intptr_t) p->fhs[0], _O_RDONLY); if (fd == -1) return NULL; + if (opts & PIPE_DUP) + fd = _dup(fd); FILE *in = _fdopen(fd, "r"); #else - if (do_close) + if (opts & PIPE_CLOSE) close(p->fds[1]); - FILE *in = fdopen(p->fds[0], "r"); + int fd = p->fds[0]; + if (opts & PIPE_DUP) + fd = dup(fd); + FILE *in = fdopen(fd, "r"); #endif if (!in) return NULL; @@ -47,18 +52,23 @@ FILE *pipe_in(s_pipe_handle *p, int do_close) { return in; } -FILE *pipe_out(s_pipe_handle *p, int do_close) { +FILE *pipe_out(s_pipe_handle *p, enum pipe_opt opts) { #ifdef VANILLA_WIN32 - if (do_close) + if (opts & PIPE_CLOSE) CloseHandle(p->fhs[0]); int fd = _open_osfhandle((intptr_t) p->fhs[1], _O_WRONLY); if (fd == -1) return NULL; + if (opts & PIPE_DUP) + fd = _dup(fd); FILE *out = _fdopen(fd, "w"); #else - if (do_close) + if (opts & PIPE_CLOSE) close(p->fds[0]); - FILE *out = fdopen(p->fds[1], "w"); + int fd = p->fds[1]; + if (opts & PIPE_DUP) + fd = dup(fd); + FILE *out = fdopen(fd, "w"); #endif if (!out) return NULL; diff --git a/src/compat/pipe.h b/src/compat/pipe.h index 2aa9d8d..83aa63d 100644 --- a/src/compat/pipe.h +++ b/src/compat/pipe.h @@ -24,6 +24,7 @@ #ifndef PIPE_H_ # define PIPE_H_ +# include # include "common.h" struct pipe_handle; @@ -40,9 +41,14 @@ enum criterion_std_fd { CR_STDERR = 2, }; +enum pipe_opt { + PIPE_DUP = 1 << 0, + PIPE_CLOSE = 1 << 1, +}; + s_pipe_handle *stdpipe(); -FILE *pipe_in(s_pipe_handle *p, int do_close); -FILE *pipe_out(s_pipe_handle *p, int do_close); +FILE *pipe_in(s_pipe_handle *p, enum pipe_opt opts); +FILE *pipe_out(s_pipe_handle *p, enum pipe_opt opts); int stdpipe_options(s_pipe_handle *pipe, int id, int noblock); void pipe_std_redirect(s_pipe_handle *pipe, enum criterion_std_fd fd); diff --git a/src/compat/process.c b/src/compat/process.c index 5204e3e..2adc7f8 100644 --- a/src/compat/process.c +++ b/src/compat/process.c @@ -21,12 +21,18 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#include +#include #include #include "core/worker.h" +#include "core/runner.h" +#include "io/event.h" #include "process.h" #include "internal.h" #include "pipe-internal.h" +#include + #ifdef VANILLA_WIN32 # define CREATE_SUSPENDED_(Filename, CmdLine, StartupInfo, Info) \ CreateProcessW(Filename, \ @@ -44,14 +50,6 @@ WriteProcessMemory(Proc, &What, &What, Size, NULL); #endif -struct proc_handle { -#ifdef VANILLA_WIN32 - HANDLE handle; -#else - pid_t pid; -#endif -}; - struct worker_context g_worker_context = {.test = NULL}; #ifdef VANILLA_WIN32 @@ -71,6 +69,32 @@ static TCHAR g_mapping_name[] = TEXT("WinCriterionWorker"); static struct full_context local_ctx; #endif +#ifdef __unix__ +# ifndef __GNUC__ +# error Unsupported compiler. Use GCC or Clang under *nixes. +# endif + +static void handle_sigchld(int sig) { + assert(sig == SIGCHLD); + + int fd = g_worker_pipe->fds[1]; + pid_t pid; + int status; + while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { + int kind = WORKER_TERMINATED; + struct worker_status ws = { + (s_proc_handle) { pid }, get_status(status) + }; + + char buf[sizeof (int) + sizeof (struct worker_status)]; + memcpy(buf, &kind, sizeof (kind)); + memcpy(buf + sizeof (kind), &ws, sizeof (ws)); + + write(fd, &buf, sizeof (buf)); + } +} +#endif + int resume_child(void) { #ifdef VANILLA_WIN32 HANDLE sharedMem = OpenFileMapping( @@ -111,6 +135,16 @@ int resume_child(void) { run_worker(&g_worker_context); return 1; #else +# ifdef __unix__ + struct sigaction sa; + sa.sa_handler = &handle_sigchld; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART | SA_NOCLDSTOP; + if (sigaction(SIGCHLD, &sa, 0) == -1) { + perror(0); + exit(1); + } +# endif return 0; #endif } diff --git a/src/compat/process.h b/src/compat/process.h index 2d5d2ef..1698522 100644 --- a/src/compat/process.h +++ b/src/compat/process.h @@ -25,8 +25,16 @@ # define COMPAT_PROCESS_H_ # include "criterion/types.h" +# include "compat/posix.h" + +struct proc_handle { +#ifdef VANILLA_WIN32 + HANDLE handle; +#else + pid_t pid; +#endif +}; -struct proc_handle; typedef struct proc_handle s_proc_handle; struct worker_context { diff --git a/src/core/runner.c b/src/core/runner.c index f085921..2635010 100644 --- a/src/core/runner.c +++ b/src/core/runner.c @@ -208,13 +208,92 @@ static INLINE bool is_disabled(struct criterion_test *t, #define push_event(Kind, ...) \ do { \ - stat_push_event(stats, \ - suite_stats, \ - test_stats, \ + stat_push_event(ctx->stats, \ + ctx->suite_stats, \ + ctx->test_stats, \ &(struct event) { .kind = Kind, __VA_ARGS__ }); \ - report(Kind, test_stats); \ + report(Kind, ctx->test_stats); \ } while (0) +s_pipe_handle *g_worker_pipe; + +struct execution_context { + bool test_started; + bool normal_finish; + bool cleaned_up; + struct criterion_global_stats *stats; + struct criterion_test *test; + struct criterion_test_stats *test_stats; + struct criterion_suite *suite; + struct criterion_suite_stats *suite_stats; +}; + +static void handle_worker_terminated(struct event *ev, + struct execution_context *ctx) { + + struct worker_status *ws = ev->data; + struct process_status status = ws->status; + + if (status.kind == SIGNAL) { + if (status.status == SIGPROF) { + ctx->test_stats->timed_out = true; + double elapsed_time = ctx->test->data->timeout; + if (elapsed_time == 0 && ctx->suite->data) + elapsed_time = ctx->suite->data->timeout; + push_event(POST_TEST, .data = &elapsed_time); + push_event(POST_FINI); + log(test_timeout, ctx->test_stats); + return; + } + + if (ctx->normal_finish || !ctx->test_started) { + log(other_crash, ctx->test_stats); + if (!ctx->test_started) { + stat_push_event(ctx->stats, + ctx->suite_stats, + ctx->test_stats, + &(struct event) { .kind = TEST_CRASH }); + } + return; + } + ctx->test_stats->signal = status.status; + if (ctx->test->data->signal == 0) { + push_event(TEST_CRASH); + log(test_crash, ctx->test_stats); + } else { + double elapsed_time = 0; + push_event(POST_TEST, .data = &elapsed_time); + log(post_test, ctx->test_stats); + push_event(POST_FINI); + log(post_fini, ctx->test_stats); + } + } else { + if ((ctx->normal_finish && !ctx->cleaned_up) || !ctx->test_started) { + log(abnormal_exit, ctx->test_stats); + if (!ctx->test_started) { + stat_push_event(ctx->stats, + ctx->suite_stats, + ctx->test_stats, + &(struct event) { .kind = TEST_CRASH }); + } + return; + } + ctx->test_stats->exit_code = status.status; + if (!ctx->normal_finish) { + if (ctx->test->data->exit_code == 0) { + push_event(TEST_CRASH); + log(abnormal_exit, ctx->test_stats); + } else { + double elapsed_time = 0; + push_event(POST_TEST, .data = &elapsed_time); + log(post_test, ctx->test_stats); + push_event(POST_FINI); + log(post_fini, ctx->test_stats); + } + } + } +} + static void run_test(struct criterion_global_stats *stats, struct criterion_suite_stats *suite_stats, struct criterion_test *test, @@ -231,16 +310,21 @@ static void run_test(struct criterion_global_stats *stats, goto cleanup; } - proc = spawn_test_worker(test, suite, run_test_child); + proc = spawn_test_worker(test, suite, run_test_child, g_worker_pipe); if (proc == NULL && !is_runner()) goto cleanup; - bool test_started = false; - bool normal_finish = false; - bool cleaned_up = false; + struct execution_context ctx = { + .stats = stats, + .test = test, + .test_stats = test_stats, + .suite = suite, + .suite_stats = suite_stats, + }; struct event *ev; while ((ev = worker_read_event(proc)) != NULL) { - stat_push_event(stats, suite_stats, test_stats, ev); + if (ev->kind < WORKER_TERMINATED) + stat_push_event(stats, suite_stats, test_stats, ev); switch (ev->kind) { case PRE_INIT: report(PRE_INIT, test); @@ -249,7 +333,7 @@ static void run_test(struct criterion_global_stats *stats, case PRE_TEST: report(PRE_TEST, test); log(pre_test, test); - test_started = true; + ctx.test_started = true; break; case THEORY_FAIL: { struct criterion_theory_stats ths = { @@ -266,77 +350,21 @@ static void run_test(struct criterion_global_stats *stats, case POST_TEST: report(POST_TEST, test_stats); log(post_test, test_stats); - normal_finish = true; + ctx.normal_finish = true; break; case POST_FINI: report(POST_FINI, test_stats); log(post_fini, test_stats); - cleaned_up = true; + ctx.cleaned_up = true; break; + case WORKER_TERMINATED: + handle_worker_terminated(ev, &ctx); + sfree(ev); + goto cleanup; } sfree(ev); } - struct process_status status = wait_proc(proc); - if (status.kind == SIGNAL) { - if (status.status == SIGPROF) { - test_stats->timed_out = true; - double elapsed_time = test->data->timeout; - if (elapsed_time == 0 && suite->data) - elapsed_time = suite->data->timeout; - push_event(POST_TEST, .data = &elapsed_time); - push_event(POST_FINI); - log(test_timeout, test_stats); - goto cleanup; - } - - if (normal_finish || !test_started) { - log(other_crash, test_stats); - if (!test_started) { - stat_push_event(stats, - suite_stats, - test_stats, - &(struct event) { .kind = TEST_CRASH }); - } - goto cleanup; - } - test_stats->signal = status.status; - if (test->data->signal == 0) { - push_event(TEST_CRASH); - log(test_crash, test_stats); - } else { - double elapsed_time = 0; - push_event(POST_TEST, .data = &elapsed_time); - log(post_test, test_stats); - push_event(POST_FINI); - log(post_fini, test_stats); - } - } else { - if ((normal_finish && !cleaned_up) || !test_started) { - log(abnormal_exit, test_stats); - if (!test_started) { - stat_push_event(stats, - suite_stats, - test_stats, - &(struct event) { .kind = TEST_CRASH }); - } - goto cleanup; - } - test_stats->exit_code = status.status; - if (!normal_finish) { - if (test->data->exit_code == 0) { - push_event(TEST_CRASH); - log(abnormal_exit, test_stats); - } else { - double elapsed_time = 0; - push_event(POST_TEST, .data = &elapsed_time); - log(post_test, test_stats); - push_event(POST_FINI); - log(post_fini, test_stats); - } - } - } - cleanup: sfree(test_stats); sfree(proc); @@ -381,6 +409,10 @@ static int criterion_run_all_tests_impl(struct criterion_test_set *set) { fflush(NULL); // flush everything before forking + g_worker_pipe = stdpipe(); + if (g_worker_pipe == NULL) + abort(); + struct criterion_global_stats *stats = stats_init(); map_tests(set, stats, run_test); diff --git a/src/core/runner.h b/src/core/runner.h index 75e12dc..74a3356 100644 --- a/src/core/runner.h +++ b/src/core/runner.h @@ -25,6 +25,7 @@ # define CRITERION_RUNNER_H_ # include "criterion/types.h" +# include "compat/pipe.h" DECL_SECTION_LIMITS(struct criterion_test, cr_tst); DECL_SECTION_LIMITS(struct criterion_suite, cr_sts); @@ -41,4 +42,6 @@ struct criterion_test_set *criterion_init(void); Suite < (struct criterion_suite*) GET_SECTION_END(cr_sts); \ ++Suite) +extern s_pipe_handle *g_worker_pipe; + #endif /* !CRITERION_RUNNER_H_ */ diff --git a/src/core/worker.c b/src/core/worker.c index f6833f8..7f53279 100644 --- a/src/core/worker.c +++ b/src/core/worker.c @@ -63,7 +63,7 @@ struct event *worker_read_event(struct process *proc) { void run_worker(struct worker_context *ctx) { cr_redirect_stdin(); - g_event_pipe = pipe_out(ctx->pipe, 1); + g_event_pipe = pipe_out(ctx->pipe, PIPE_CLOSE); ctx->func(ctx->test, ctx->suite); fclose(g_event_pipe); @@ -76,11 +76,8 @@ void run_worker(struct worker_context *ctx) { struct process *spawn_test_worker(struct criterion_test *test, struct criterion_suite *suite, - f_worker_func func) { - s_pipe_handle *pipe = stdpipe(); - if (pipe == NULL) - abort(); - + f_worker_func func, + s_pipe_handle *pipe) { g_worker_context = (struct worker_context) { .test = test, .suite = suite, @@ -92,10 +89,10 @@ struct process *spawn_test_worker(struct criterion_test *test, s_proc_handle *proc = fork_process(); if (proc == (void *) -1) { - goto cleanup; + return NULL; } else if (proc == NULL) { run_worker(&g_worker_context); - goto cleanup; + return NULL; } ptr = smalloc( @@ -103,16 +100,11 @@ struct process *spawn_test_worker(struct criterion_test *test, .kind = UNIQUE, .dtor = close_process); - *ptr = (struct process) { .proc = proc, .in = pipe_in(pipe, 1) }; -cleanup: - sfree(pipe); + *ptr = (struct process) { .proc = proc, .in = pipe_in(pipe, PIPE_DUP) }; return ptr; } -struct process_status wait_proc(struct process *proc) { - int status; - wait_process(proc->proc, &status); - +struct process_status get_status(int status) { if (WIFEXITED(status)) return (struct process_status) { .kind = EXIT_STATUS, @@ -127,3 +119,10 @@ struct process_status wait_proc(struct process *proc) { return (struct process_status) { .kind = STOPPED }; } + +struct process_status wait_proc(struct process *proc) { + int status; + wait_process(proc->proc, &status); + + return get_status(status); +} diff --git a/src/core/worker.h b/src/core/worker.h index 2f63406..5cc7af7 100644 --- a/src/core/worker.h +++ b/src/core/worker.h @@ -25,7 +25,9 @@ # define PROCESS_H_ # include +# include "criterion/types.h" # include "compat/process.h" +# include "compat/pipe.h" struct process; @@ -40,14 +42,21 @@ struct process_status { int status; }; +struct worker_status { + s_proc_handle proc; + struct process_status status; +}; + void run_worker(struct worker_context *ctx); void set_runner_process(void); void unset_runner_process(void); bool is_runner(void); struct process_status wait_proc(struct process *proc); +struct process_status get_status(int status); struct process *spawn_test_worker(struct criterion_test *test, struct criterion_suite *suite, - void (*func)(struct criterion_test *, struct criterion_suite *)); + f_worker_func func, + s_pipe_handle *pipe); struct event *worker_read_event(struct process *proc); #endif /* !PROCESS_H_ */ diff --git a/src/io/event.c b/src/io/event.c index abb85a6..1ba6a26 100644 --- a/src/io/event.c +++ b/src/io/event.c @@ -28,6 +28,7 @@ #include "criterion/stats.h" #include "criterion/common.h" #include "criterion/hooks.h" +#include "core/worker.h" #include "event.h" FILE *g_event_pipe = NULL; @@ -112,6 +113,20 @@ fail_assert: *ev = (struct event) { .kind = kind, .data = elapsed_time }; return ev; } + case WORKER_TERMINATED: { + struct worker_status *status = malloc(sizeof (struct worker_status)); + if (fread(status, sizeof (struct worker_status), 1, f) == 0) { + free(status); + return NULL; + } + + struct event *ev = smalloc( + .size = sizeof (struct event), + .dtor = destroy_event + ); + *ev = (struct event) { .kind = kind, .data = status }; + return ev; + } default: { struct event *ev = smalloc(sizeof (struct event)); *ev = (struct event) { .kind = kind, .data = NULL }; diff --git a/src/io/event.h b/src/io/event.h index 21d9b21..64c30ac 100644 --- a/src/io/event.h +++ b/src/io/event.h @@ -34,6 +34,10 @@ struct event { void *data; }; +enum other_event_kinds { + WORKER_TERMINATED = 1 << 30, +}; + struct event *read_event(FILE *f); #endif /* !EVENT_H_ */ From 0850658785a182d3acdcf530e1e0b66c7fc5c258 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 17 Sep 2015 04:35:47 +0200 Subject: [PATCH 2/4] Changed the windows worker waiting code as well --- src/compat/process.c | 118 ++++++++++++++++++++++++++++++------------- src/compat/process.h | 1 + 2 files changed, 83 insertions(+), 36 deletions(-) diff --git a/src/compat/process.c b/src/compat/process.c index 2adc7f8..8acfec9 100644 --- a/src/compat/process.c +++ b/src/compat/process.c @@ -48,8 +48,47 @@ # define WRITE_PROCESS_(Proc, What, Size) \ WriteProcessMemory(Proc, &What, &What, Size, NULL); + +static int get_win_status(HANDLE handle) { + DWORD exit_code; + GetExitCodeProcess(handle, &exit_code); + unsigned int sig = 0; + switch (exit_code) { + case STATUS_FLOAT_DENORMAL_OPERAND: + case STATUS_FLOAT_DIVIDE_BY_ZERO: + case STATUS_FLOAT_INEXACT_RESULT: + case STATUS_FLOAT_INVALID_OPERATION: + case STATUS_FLOAT_OVERFLOW: + case STATUS_FLOAT_STACK_CHECK: + case STATUS_FLOAT_UNDERFLOW: + case STATUS_INTEGER_DIVIDE_BY_ZERO: + case STATUS_INTEGER_OVERFLOW: sig = SIGFPE; break; + + case STATUS_ILLEGAL_INSTRUCTION: + case STATUS_PRIVILEGED_INSTRUCTION: + case STATUS_NONCONTINUABLE_EXCEPTION: sig = SIGILL; break; + + case CR_EXCEPTION_TIMEOUT: sig = SIGPROF; break; + + case STATUS_ACCESS_VIOLATION: + case STATUS_DATATYPE_MISALIGNMENT: + case STATUS_ARRAY_BOUNDS_EXCEEDED: + case STATUS_GUARD_PAGE_VIOLATION: + case STATUS_IN_PAGE_ERROR: + case STATUS_NO_MEMORY: + case STATUS_INVALID_DISPOSITION: + case STATUS_STACK_OVERFLOW: sig = SIGSEGV; break; + + case STATUS_CONTROL_C_EXIT: sig = SIGINT; break; + + default: break; + } + return sig ? sig : exit_code << 8; +} #endif + + struct worker_context g_worker_context = {.test = NULL}; #ifdef VANILLA_WIN32 @@ -95,6 +134,37 @@ static void handle_sigchld(int sig) { } #endif +#ifdef VANILLA_WIN32 +struct wait_context { + HANDLE wait_handle; + HANDLE proc_handle; +}; + +static void handle_child_terminated(PVOID lpParameter, + BOOLEAN TimerOrWaitFired) { + + assert(!TimerOrWaitFired); + + struct wait_context *wctx = lpParameter; + + int status = get_win_status(wctx->proc_handle); + int kind = WORKER_TERMINATED; + struct worker_status ws = { + (s_proc_handle) { wctx->proc_handle }, get_status(status) + }; + + char buf[sizeof (int) + sizeof (struct worker_status)]; + memcpy(buf, &kind, sizeof (kind)); + memcpy(buf + sizeof (kind), &ws, sizeof (ws)); + + WriteFile(g_worker_pipe->fhs[1], buf, sizeof (buf), NULL, NULL); + + HANDLE whandle = wctx->wait_handle; + free(lpParameter); + UnregisterWaitEx(whandle, NULL); +} +#endif + int resume_child(void) { #ifdef VANILLA_WIN32 HANDLE sharedMem = OpenFileMapping( @@ -206,6 +276,17 @@ s_proc_handle *fork_process() { UnmapViewOfFile(ctx); CloseHandle(sharedMem); + struct wait_context *wctx = malloc(sizeof (struct wait_context)); + *wctx = {} + + RegisterWaitForSingleObject( + &wctx->wait_handle, + info.hProcess, + handle_child_terminated, + wctx, + INFINITE, + WT_EXECUTELONGFUNCTION | WT_EXECUTEONLYONCE); + s_proc_handle *handle = smalloc(sizeof (s_proc_handle)); *handle = (s_proc_handle) { info.hProcess }; return handle; @@ -225,43 +306,8 @@ s_proc_handle *fork_process() { void wait_process(s_proc_handle *handle, int *status) { #ifdef VANILLA_WIN32 WaitForSingleObject(handle->handle, INFINITE); - DWORD exit_code; - GetExitCodeProcess(handle->handle, &exit_code); + *status = get_win_status(handle->handle); CloseHandle(handle->handle); - - unsigned int sig = 0; - switch (exit_code) { - case STATUS_FLOAT_DENORMAL_OPERAND: - case STATUS_FLOAT_DIVIDE_BY_ZERO: - case STATUS_FLOAT_INEXACT_RESULT: - case STATUS_FLOAT_INVALID_OPERATION: - case STATUS_FLOAT_OVERFLOW: - case STATUS_FLOAT_STACK_CHECK: - case STATUS_FLOAT_UNDERFLOW: - case STATUS_INTEGER_DIVIDE_BY_ZERO: - case STATUS_INTEGER_OVERFLOW: sig = SIGFPE; break; - - case STATUS_ILLEGAL_INSTRUCTION: - case STATUS_PRIVILEGED_INSTRUCTION: - case STATUS_NONCONTINUABLE_EXCEPTION: sig = SIGILL; break; - - case CR_EXCEPTION_TIMEOUT: sig = SIGPROF; break; - - case STATUS_ACCESS_VIOLATION: - case STATUS_DATATYPE_MISALIGNMENT: - case STATUS_ARRAY_BOUNDS_EXCEEDED: - case STATUS_GUARD_PAGE_VIOLATION: - case STATUS_IN_PAGE_ERROR: - case STATUS_NO_MEMORY: - case STATUS_INVALID_DISPOSITION: - case STATUS_STACK_OVERFLOW: sig = SIGSEGV; break; - - case STATUS_CONTROL_C_EXIT: sig = SIGINT; break; - - default: break; - } - - *status = sig ? sig : exit_code << 8; #else waitpid(handle->pid, status, 0); #endif diff --git a/src/compat/process.h b/src/compat/process.h index 1698522..d38b995 100644 --- a/src/compat/process.h +++ b/src/compat/process.h @@ -26,6 +26,7 @@ # include "criterion/types.h" # include "compat/posix.h" +# include "internal.h" struct proc_handle { #ifdef VANILLA_WIN32 From e011939d5e98369442e4d0217d4c71989226ae2c Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 17 Sep 2015 06:09:56 -0700 Subject: [PATCH 3/4] Fixed OSX not registering the sigchld handler --- src/compat/process.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compat/process.c b/src/compat/process.c index 8acfec9..f196b8c 100644 --- a/src/compat/process.c +++ b/src/compat/process.c @@ -108,7 +108,7 @@ static TCHAR g_mapping_name[] = TEXT("WinCriterionWorker"); static struct full_context local_ctx; #endif -#ifdef __unix__ +#if defined(__unix__) || defined(__APPLE__) # ifndef __GNUC__ # error Unsupported compiler. Use GCC or Clang under *nixes. # endif @@ -205,7 +205,7 @@ int resume_child(void) { run_worker(&g_worker_context); return 1; #else -# ifdef __unix__ +# if defined(__unix__) || defined(__APPLE__) struct sigaction sa; sa.sa_handler = &handle_sigchld; sigemptyset(&sa.sa_mask); From ab9763c8cfddeca1e28b01ebb096b3cc99aa7153 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 17 Sep 2015 06:30:04 -0700 Subject: [PATCH 4/4] Fixed windows async worker termination reporting --- src/compat/internal.h | 6 +++--- src/compat/process.c | 11 +++++++---- src/compat/process.h | 1 - 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/compat/internal.h b/src/compat/internal.h index 04f257e..29b73ab 100644 --- a/src/compat/internal.h +++ b/src/compat/internal.h @@ -24,9 +24,7 @@ #ifndef INTERNAL_H_ # define INTERNAL_H_ -# include "posix.h" - -# ifdef VANILLA_WIN32 +# if defined(_WIN32) && !defined(__CYGWIN__) # define VC_EXTRALEAN # define WIN32_LEAN_AND_MEAN # undef _WIN32_WINNT @@ -44,4 +42,6 @@ # include # endif +# include "posix.h" + #endif /* !INTERNAL_H_ */ diff --git a/src/compat/process.c b/src/compat/process.c index f196b8c..f5c03bc 100644 --- a/src/compat/process.c +++ b/src/compat/process.c @@ -140,8 +140,8 @@ struct wait_context { HANDLE proc_handle; }; -static void handle_child_terminated(PVOID lpParameter, - BOOLEAN TimerOrWaitFired) { +static void CALLBACK handle_child_terminated(PVOID lpParameter, + BOOLEAN TimerOrWaitFired) { assert(!TimerOrWaitFired); @@ -157,7 +157,8 @@ static void handle_child_terminated(PVOID lpParameter, memcpy(buf, &kind, sizeof (kind)); memcpy(buf + sizeof (kind), &ws, sizeof (ws)); - WriteFile(g_worker_pipe->fhs[1], buf, sizeof (buf), NULL, NULL); + DWORD written; + WriteFile(g_worker_pipe->fhs[1], buf, sizeof (buf), &written, NULL); HANDLE whandle = wctx->wait_handle; free(lpParameter); @@ -277,7 +278,9 @@ s_proc_handle *fork_process() { CloseHandle(sharedMem); struct wait_context *wctx = malloc(sizeof (struct wait_context)); - *wctx = {} + *wctx = (struct wait_context) { + .proc_handle = info.hProcess, + }; RegisterWaitForSingleObject( &wctx->wait_handle, diff --git a/src/compat/process.h b/src/compat/process.h index d38b995..2e26db4 100644 --- a/src/compat/process.h +++ b/src/compat/process.h @@ -25,7 +25,6 @@ # define COMPAT_PROCESS_H_ # include "criterion/types.h" -# include "compat/posix.h" # include "internal.h" struct proc_handle {