mirror of
https://github.com/janet-lang/janet
synced 2025-10-24 20:27:41 +00:00
Merge pull request #1645 from pyrmont/bugfix.avoid-apc-use
Use `SetEvent` rather than `QueueUserAPC` on Windows
This commit is contained in:
@@ -117,6 +117,9 @@ typedef struct {
|
|||||||
double sec;
|
double sec;
|
||||||
JanetVM *vm;
|
JanetVM *vm;
|
||||||
JanetFiber *fiber;
|
JanetFiber *fiber;
|
||||||
|
#ifdef JANET_WINDOWS
|
||||||
|
HANDLE cancel_event;
|
||||||
|
#endif
|
||||||
} JanetThreadedTimeout;
|
} JanetThreadedTimeout;
|
||||||
|
|
||||||
#define JANET_MAX_Q_CAPACITY 0x7FFFFFF
|
#define JANET_MAX_Q_CAPACITY 0x7FFFFFF
|
||||||
@@ -604,12 +607,7 @@ void janet_ev_init_common(void) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JANET_WINDOWS
|
#if JANET_ANDROID
|
||||||
static VOID CALLBACK janet_timeout_stop(ULONG_PTR ptr) {
|
|
||||||
UNREFERENCED_PARAMETER(ptr);
|
|
||||||
ExitThread(0);
|
|
||||||
}
|
|
||||||
#elif JANET_ANDROID
|
|
||||||
static void janet_timeout_stop(int sig_num) {
|
static void janet_timeout_stop(int sig_num) {
|
||||||
if (sig_num == SIGUSR1) {
|
if (sig_num == SIGUSR1) {
|
||||||
pthread_exit(0);
|
pthread_exit(0);
|
||||||
@@ -620,10 +618,14 @@ static void janet_timeout_stop(int sig_num) {
|
|||||||
static void handle_timeout_worker(JanetTimeout to, int cancel) {
|
static void handle_timeout_worker(JanetTimeout to, int cancel) {
|
||||||
if (!to.has_worker) return;
|
if (!to.has_worker) return;
|
||||||
#ifdef JANET_WINDOWS
|
#ifdef JANET_WINDOWS
|
||||||
(void) cancel;
|
if (cancel && to.worker_event) {
|
||||||
QueueUserAPC(janet_timeout_stop, to.worker, 0);
|
SetEvent(to.worker_event);
|
||||||
|
}
|
||||||
WaitForSingleObject(to.worker, INFINITE);
|
WaitForSingleObject(to.worker, INFINITE);
|
||||||
CloseHandle(to.worker);
|
CloseHandle(to.worker);
|
||||||
|
if (to.worker_event) {
|
||||||
|
CloseHandle(to.worker_event);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
#ifdef JANET_ANDROID
|
#ifdef JANET_ANDROID
|
||||||
if (cancel) janet_assert(!pthread_kill(to.worker, SIGUSR1), "pthread_kill");
|
if (cancel) janet_assert(!pthread_kill(to.worker, SIGUSR1), "pthread_kill");
|
||||||
@@ -693,10 +695,20 @@ static void janet_timeout_cb(JanetEVGenericMessage msg) {
|
|||||||
static DWORD WINAPI janet_timeout_body(LPVOID ptr) {
|
static DWORD WINAPI janet_timeout_body(LPVOID ptr) {
|
||||||
JanetThreadedTimeout tto = *(JanetThreadedTimeout *)ptr;
|
JanetThreadedTimeout tto = *(JanetThreadedTimeout *)ptr;
|
||||||
janet_free(ptr);
|
janet_free(ptr);
|
||||||
SleepEx((DWORD)(tto.sec * 1000), TRUE);
|
JanetTimestamp wait_begin = ts_now();
|
||||||
|
DWORD duration = (DWORD)round(tto.sec * 1000);
|
||||||
|
DWORD res = WAIT_TIMEOUT;
|
||||||
|
JanetTimestamp wait_end = ts_now();
|
||||||
|
for (size_t i = 1; res == WAIT_TIMEOUT && (wait_end - wait_begin) < duration; i++) {
|
||||||
|
res = WaitForSingleObject(tto.cancel_event, (duration + i));
|
||||||
|
wait_end = ts_now();
|
||||||
|
}
|
||||||
|
/* only send interrupt message if result is WAIT_TIMEOUT */
|
||||||
|
if (res == WAIT_TIMEOUT) {
|
||||||
janet_interpreter_interrupt(tto.vm);
|
janet_interpreter_interrupt(tto.vm);
|
||||||
JanetEVGenericMessage msg = {0};
|
JanetEVGenericMessage msg = {0};
|
||||||
janet_ev_post_event(tto.vm, janet_timeout_cb, msg);
|
janet_ev_post_event(tto.vm, janet_timeout_cb, msg);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -3270,7 +3282,13 @@ JANET_CORE_FN(cfun_ev_deadline,
|
|||||||
tto->vm = &janet_vm;
|
tto->vm = &janet_vm;
|
||||||
tto->fiber = tocheck;
|
tto->fiber = tocheck;
|
||||||
#ifdef JANET_WINDOWS
|
#ifdef JANET_WINDOWS
|
||||||
HANDLE worker = CreateThread(NULL, 0, janet_timeout_body, tto, 0, NULL);
|
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, CREATE_SUSPENDED, NULL);
|
||||||
if (NULL == worker) {
|
if (NULL == worker) {
|
||||||
janet_free(tto);
|
janet_free(tto);
|
||||||
janet_panic("failed to create thread");
|
janet_panic("failed to create thread");
|
||||||
@@ -3285,6 +3303,10 @@ JANET_CORE_FN(cfun_ev_deadline,
|
|||||||
#endif
|
#endif
|
||||||
to.has_worker = 1;
|
to.has_worker = 1;
|
||||||
to.worker = worker;
|
to.worker = worker;
|
||||||
|
#ifdef JANET_WINDOWS
|
||||||
|
to.worker_event = cancel_event;
|
||||||
|
ResumeThread(worker);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
to.has_worker = 0;
|
to.has_worker = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ typedef struct {
|
|||||||
int has_worker;
|
int has_worker;
|
||||||
#ifdef JANET_WINDOWS
|
#ifdef JANET_WINDOWS
|
||||||
HANDLE worker;
|
HANDLE worker;
|
||||||
|
HANDLE worker_event;
|
||||||
#else
|
#else
|
||||||
pthread_t worker;
|
pthread_t worker;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user