From aca5428846cb961b8a443f6b36d3cdba70487fd6 Mon Sep 17 00:00:00 2001 From: Michael Camilleri Date: Tue, 16 Sep 2025 10:24:24 +0900 Subject: [PATCH] Use SetEvent rather than QueueUserAPC on Windows --- src/core/ev.c | 31 +++++++++++++++++++++++++------ src/core/state.h | 1 + 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/core/ev.c b/src/core/ev.c index 3acf9dd6..8422168a 100644 --- a/src/core/ev.c +++ b/src/core/ev.c @@ -117,6 +117,9 @@ typedef struct { double sec; JanetVM *vm; JanetFiber *fiber; +#ifdef JANET_WINDOWS + HANDLE cancel_event; +#endif } JanetThreadedTimeout; #define JANET_MAX_Q_CAPACITY 0x7FFFFFF @@ -620,10 +623,14 @@ static void janet_timeout_stop(int sig_num) { static void handle_timeout_worker(JanetTimeout to, int cancel) { if (!to.has_worker) return; #ifdef JANET_WINDOWS - (void) cancel; - QueueUserAPC(janet_timeout_stop, to.worker, 0); + if (cancel && to.worker_event) { + SetEvent(to.worker_event); + } WaitForSingleObject(to.worker, INFINITE); CloseHandle(to.worker); + if (to.worker_event) { + CloseHandle(to.worker_event); + } #else #ifdef JANET_ANDROID if (cancel) janet_assert(!pthread_kill(to.worker, SIGUSR1), "pthread_kill"); @@ -693,10 +700,13 @@ static void janet_timeout_cb(JanetEVGenericMessage msg) { static DWORD WINAPI janet_timeout_body(LPVOID ptr) { JanetThreadedTimeout tto = *(JanetThreadedTimeout *)ptr; janet_free(ptr); - SleepEx((DWORD)(tto.sec * 1000), TRUE); - janet_interpreter_interrupt(tto.vm); - JanetEVGenericMessage msg = {0}; - janet_ev_post_event(tto.vm, janet_timeout_cb, msg); + DWORD res = WaitForSingleObject(tto.cancel_event, (DWORD)(tto.sec * 1000)); + /* only send interrupt message if result is WAIT_TIMEOUT */ + if (res == WAIT_TIMEOUT) { + janet_interpreter_interrupt(tto.vm); + JanetEVGenericMessage msg = {0}; + janet_ev_post_event(tto.vm, janet_timeout_cb, msg); + } return 0; } #else @@ -3270,6 +3280,12 @@ JANET_CORE_FN(cfun_ev_deadline, tto->vm = &janet_vm; tto->fiber = tocheck; #ifdef JANET_WINDOWS + HANDLE cancel_event = CreateEvent(NULL, TRUE, FALSE, NULL); + if (NULL == cancel_event) { + janet_free(tto); + janet_panic("failed to create cancel event"); + } + tto->cancel_event = cancel_event; HANDLE worker = CreateThread(NULL, 0, janet_timeout_body, tto, 0, NULL); if (NULL == worker) { janet_free(tto); @@ -3285,6 +3301,9 @@ JANET_CORE_FN(cfun_ev_deadline, #endif to.has_worker = 1; to.worker = worker; +#ifdef JANET_WINDOWS + to.worker_event = cancel_event; +#endif } else { to.has_worker = 0; } diff --git a/src/core/state.h b/src/core/state.h index 918c1ade..6c9add74 100644 --- a/src/core/state.h +++ b/src/core/state.h @@ -65,6 +65,7 @@ typedef struct { int has_worker; #ifdef JANET_WINDOWS HANDLE worker; + HANDLE worker_event; #else pthread_t worker; #endif