Mark a fiber as a root fiber during scheduling, not resumption.

This is more intuitive and avoids the possibilty of strange code
to resume or cancel a fiber after it was scheduled but before it was
entered for the first time.
This commit is contained in:
Calvin Rose 2022-02-10 17:40:08 -06:00
parent aba87bf1bd
commit 2f068b91d8
2 changed files with 4 additions and 5 deletions

View File

@ -465,6 +465,7 @@ const JanetAbstractType janet_stream_type = {
/* Register a fiber to resume with value */
void janet_schedule_signal(JanetFiber *fiber, Janet value, JanetSignal sig) {
if (fiber->gc.flags & JANET_FIBER_EV_FLAG_CANCELED) return;
fiber->gc.flags |= JANET_FIBER_FLAG_ROOT;
JanetTask t = { fiber, value, sig, ++fiber->sched_id };
if (sig == JANET_SIGNAL_ERROR) fiber->gc.flags |= JANET_FIBER_EV_FLAG_CANCELED;
janet_q_push(&janet_vm.spawn, &t, sizeof(t));

View File

@ -1338,8 +1338,9 @@ static JanetSignal janet_check_can_resume(JanetFiber *fiber, Janet *out, int is_
*out = janet_cstringv("C stack recursed too deeply");
return JANET_SIGNAL_ERROR;
}
/* If a "task" fiber is trying to be used as a normal fiber, detect that. See bug #920. */
if (janet_vm.stackn > 0 && (fiber->gc.flags & JANET_FIBER_FLAG_ROOT)) {
/* If a "task" fiber is trying to be used as a normal fiber, detect that. See bug #920.
* Fibers must be marked as root fibers manually, or by the ev scheduler. */
if (janet_vm.fiber != NULL && (fiber->gc.flags & JANET_FIBER_FLAG_ROOT)) {
#ifdef JANET_EV
*out = janet_cstringv(is_cancel
? "cannot cancel root fiber, use ev/cancel"
@ -1351,9 +1352,6 @@ static JanetSignal janet_check_can_resume(JanetFiber *fiber, Janet *out, int is_
#endif
return JANET_SIGNAL_ERROR;
}
if (janet_vm.stackn == 0) {
fiber->gc.flags |= JANET_FIBER_FLAG_ROOT;
}
if (old_status == JANET_STATUS_ALIVE ||
old_status == JANET_STATUS_DEAD ||
(old_status >= JANET_STATUS_USER0 && old_status <= JANET_STATUS_USER4) ||