mruby-fiber/fiber.c: detect resume/transfer mixture; fix #5905

Also, transferred fibers should kick the root fiber at termination.
This commit is contained in:
Yukihiro "Matz" Matsumoto
2023-01-12 07:23:35 +09:00
parent 9211bf0950
commit a96a9f2c2b
2 changed files with 34 additions and 15 deletions
+24 -4
View File
@@ -202,6 +202,10 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr
enum mrb_fiber_state status;
mrb_value value;
if (resume && c == mrb->c) {
return fiber_error(mrb, "attempt to resume the current fiber");
}
fiber_check_cfunc(mrb, c);
status = c->status;
switch (status) {
@@ -220,8 +224,15 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr
default:
break;
}
old_c->status = resume ? MRB_FIBER_RESUMED : MRB_FIBER_TRANSFERRED;
c->prev = resume ? mrb->c : (c->prev ? c->prev : mrb->root_c);
if (resume) {
old_c->status = MRB_FIBER_RESUMED;
c->prev = mrb->c;
}
else {
old_c->status = MRB_FIBER_TRANSFERRED;
// c->prev = mrb->root_c;
c->prev = NULL;
}
fiber_switch_context(mrb, c);
if (status == MRB_FIBER_CREATED) {
mrb_value *b, *e;
@@ -353,6 +364,10 @@ fiber_transfer(mrb_state *mrb, mrb_value self)
fiber_check_cfunc(mrb, mrb->c);
mrb_get_args(mrb, "*!", &a, &len);
if (c->status == MRB_FIBER_RESUMED) {
mrb_raise(mrb, E_FIBER_ERROR, "attempt to transfer to a resuming fiber");
}
if (c == mrb->root_c) {
mrb->c->status = MRB_FIBER_TRANSFERRED;
fiber_switch_context(mrb, c);
@@ -373,11 +388,16 @@ mrb_fiber_yield(mrb_state *mrb, mrb_int len, const mrb_value *a)
struct mrb_context *c = mrb->c;
if (!c->prev) {
mrb_raise(mrb, E_FIBER_ERROR, "can't yield from root fiber");
return fiber_error(mrb, "attempt to yield on a not resumed fiber");
}
if (c == mrb->root_c) {
return fiber_error(mrb, "can't yield from root fiber");
}
if (c->prev->status == MRB_FIBER_TRANSFERRED) {
return fiber_error(mrb, "attempt to yield on a not resumed fiber");
}
fiber_check_cfunc(mrb, c);
c->prev->status = MRB_FIBER_RUNNING;
c->status = MRB_FIBER_SUSPENDED;
fiber_switch_context(mrb, c->prev);
c->prev = NULL;
+10 -11
View File
@@ -2170,19 +2170,18 @@ RETRY_TRY_BLOCK:
}
pc = ci[0].pc;
}
else if (mrb->c == mrb->root_c) {
mrb->c->ci->stack = mrb->c->stbase;
goto L_STOP;
}
else {
if (mrb->c == mrb->root_c) {
mrb->c->ci->stack = mrb->c->stbase;
goto L_STOP;
}
else {
struct mrb_context *c = mrb->c;
struct mrb_context *c = mrb->c;
c->status = MRB_FIBER_TERMINATED;
mrb->c = c->prev;
c->prev = NULL;
goto L_RAISE;
}
c->status = MRB_FIBER_TERMINATED;
mrb->c = c->prev;
c->prev = NULL;
if (!mrb->c) mrb->c = mrb->root_c;
goto L_RAISE;
}
}