mirror of
https://github.com/janet-lang/janet
synced 2025-07-06 12:02:53 +00:00
Work on #1596 - No detached threads, make sure to call pthread_join
Call pthread_join on all worker threads for timeouts. Previously, we were leaking some threads, as well as creating a timeout and leaving has_worker unset on certain timeouts.
This commit is contained in:
parent
790a4f2636
commit
5bbfcdacd5
@ -604,8 +604,31 @@ void janet_ev_init_common(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static void handle_timeout_worker(JanetTimeout to) {
|
||||
if (!to.has_worker) return;
|
||||
#ifdef JANET_WINDOWS
|
||||
QueueUserAPC(janet_timeout_stop, to.worker, 0);
|
||||
WaitForSingleObject(to.worker, INFINITE);
|
||||
CloseHandle(to.worker);
|
||||
#else
|
||||
#ifdef JANET_ANDROID
|
||||
pthread_kill(to.worker, SIGUSR1);
|
||||
#else
|
||||
int ret = pthread_cancel(to.worker);
|
||||
janet_assert(!ret, "pthread_cancel");
|
||||
#endif
|
||||
void *res = NULL;
|
||||
janet_assert(!pthread_join(to.worker, &res), "pthread_join");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Common deinit code */
|
||||
void janet_ev_deinit_common(void) {
|
||||
JanetTimeout to;
|
||||
while (peek_timeout(&to)) {
|
||||
handle_timeout_worker(to);
|
||||
pop_timeout(0);
|
||||
}
|
||||
janet_q_deinit(&janet_vm.spawn);
|
||||
janet_free(janet_vm.tq);
|
||||
janet_table_deinit(&janet_vm.threaded_abstracts);
|
||||
@ -1434,6 +1457,7 @@ JanetFiber *janet_loop1(void) {
|
||||
JanetTimestamp now = ts_now();
|
||||
while (peek_timeout(&to) && to.when <= now) {
|
||||
pop_timeout(0);
|
||||
handle_timeout_worker(to);
|
||||
if (to.curr_fiber != NULL) {
|
||||
if (janet_fiber_can_resume(to.curr_fiber)) {
|
||||
janet_cancel(to.fiber, janet_cstringv("deadline expired"));
|
||||
@ -1495,27 +1519,14 @@ JanetFiber *janet_loop1(void) {
|
||||
while ((has_timeout = peek_timeout(&to))) {
|
||||
if (to.curr_fiber != NULL) {
|
||||
if (!janet_fiber_can_resume(to.curr_fiber)) {
|
||||
if (to.has_worker) {
|
||||
#ifdef JANET_WINDOWS
|
||||
QueueUserAPC(janet_timeout_stop, to.worker, 0);
|
||||
WaitForSingleObject(to.worker, INFINITE);
|
||||
CloseHandle(to.worker);
|
||||
#else
|
||||
#ifdef JANET_ANDROID
|
||||
pthread_kill(to.worker, SIGUSR1);
|
||||
#else
|
||||
pthread_cancel(to.worker);
|
||||
#endif
|
||||
void *res;
|
||||
pthread_join(to.worker, &res);
|
||||
#endif
|
||||
}
|
||||
janet_table_remove(&janet_vm.active_tasks, janet_wrap_fiber(to.curr_fiber));
|
||||
pop_timeout(0);
|
||||
janet_table_remove(&janet_vm.active_tasks, janet_wrap_fiber(to.curr_fiber));
|
||||
handle_timeout_worker(to);
|
||||
continue;
|
||||
}
|
||||
} else if (to.fiber->sched_id != to.sched_id) {
|
||||
pop_timeout(0);
|
||||
handle_timeout_worker(to);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
@ -3170,6 +3181,7 @@ JANET_NO_RETURN void janet_sleep_await(double sec) {
|
||||
to.is_error = 0;
|
||||
to.sched_id = to.fiber->sched_id;
|
||||
to.curr_fiber = NULL;
|
||||
to.has_worker = 0;
|
||||
add_timeout(to);
|
||||
janet_await();
|
||||
}
|
||||
@ -3227,7 +3239,6 @@ JANET_CORE_FN(cfun_ev_deadline,
|
||||
janet_free(tto);
|
||||
janet_panicf("%s", janet_strerror(err));
|
||||
}
|
||||
janet_assert(!pthread_detach(worker), "pthread_detach");
|
||||
#endif
|
||||
to.has_worker = 1;
|
||||
to.worker = worker;
|
||||
|
@ -546,9 +546,33 @@
|
||||
(ev/sleep 0.15)
|
||||
(assert (not terminated-normally) "early termination failure 3"))
|
||||
|
||||
(let [f (coro (forever :foo))]
|
||||
(ev/deadline 0.01 nil f true)
|
||||
(assert-error "deadline expired" (resume f)))
|
||||
# Deadline with interrupt
|
||||
(defmacro with-deadline2
|
||||
``
|
||||
Create a fiber to execute `body`, schedule the event loop to cancel
|
||||
the task (root fiber) associated with `body`'s fiber, and start
|
||||
`body`'s fiber by resuming it.
|
||||
|
||||
The event loop will try to cancel the root fiber if `body`'s fiber
|
||||
has not completed after at least `sec` seconds.
|
||||
|
||||
`sec` is a number that can have a fractional part.
|
||||
``
|
||||
[sec & body]
|
||||
(with-syms [f]
|
||||
~(let [,f (coro ,;body)]
|
||||
(,ev/deadline ,sec nil ,f true)
|
||||
(,resume ,f))))
|
||||
|
||||
(repeat 10
|
||||
(assert (= :done (with-deadline2 10
|
||||
(ev/sleep 0.01)
|
||||
:done)) "deadline with interrupt exits normally"))
|
||||
|
||||
(repeat 10
|
||||
(let [f (coro (forever :foo))]
|
||||
(ev/deadline 0.01 nil f true)
|
||||
(assert-error "deadline expired" (resume f))))
|
||||
|
||||
# Use :err :stdout
|
||||
(def- subproc-code '(do (eprint "hi") (eflush) (print "there") (flush)))
|
||||
|
Loading…
x
Reference in New Issue
Block a user