From 0850658785a182d3acdcf530e1e0b66c7fc5c258 Mon Sep 17 00:00:00 2001 From: Snaipe Date: Thu, 17 Sep 2015 04:35:47 +0200 Subject: [PATCH] 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