Extend stack when pushing arguments that does not fit in; fix #4038

parent ff0a4f78
...@@ -184,26 +184,27 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr ...@@ -184,26 +184,27 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr
{ {
struct mrb_context *c = fiber_check(mrb, self); struct mrb_context *c = fiber_check(mrb, self);
struct mrb_context *old_c = mrb->c; struct mrb_context *old_c = mrb->c;
enum mrb_fiber_state status;
mrb_value value; mrb_value value;
fiber_check_cfunc(mrb, c); fiber_check_cfunc(mrb, c);
if (resume && c->status == MRB_FIBER_TRANSFERRED) { status = c->status;
if (resume && status == MRB_FIBER_TRANSFERRED) {
mrb_raise(mrb, E_FIBER_ERROR, "resuming transferred fiber"); mrb_raise(mrb, E_FIBER_ERROR, "resuming transferred fiber");
} }
if (c->status == MRB_FIBER_RUNNING || c->status == MRB_FIBER_RESUMED) { if (status == MRB_FIBER_RUNNING || status == MRB_FIBER_RESUMED) {
mrb_raise(mrb, E_FIBER_ERROR, "double resume (fib)"); mrb_raise(mrb, E_FIBER_ERROR, "double resume (fib)");
} }
if (c->status == MRB_FIBER_TERMINATED) { if (status == MRB_FIBER_TERMINATED) {
mrb_raise(mrb, E_FIBER_ERROR, "resuming dead fiber"); mrb_raise(mrb, E_FIBER_ERROR, "resuming dead fiber");
} }
mrb->c->status = resume ? MRB_FIBER_RESUMED : MRB_FIBER_TRANSFERRED; old_c->status = resume ? MRB_FIBER_RESUMED : MRB_FIBER_TRANSFERRED;
c->prev = resume ? mrb->c : (c->prev ? c->prev : mrb->root_c); c->prev = resume ? mrb->c : (c->prev ? c->prev : mrb->root_c);
if (c->status == MRB_FIBER_CREATED) { fiber_switch_context(mrb, c);
if (status == MRB_FIBER_CREATED) {
mrb_value *b, *e; mrb_value *b, *e;
if (len >= c->stend - c->stack) { mrb_stack_extend(mrb, len+2); /* for receiver and (optional) block */
mrb_raise(mrb, E_FIBER_ERROR, "too many arguments to fiber");
}
b = c->stack+1; b = c->stack+1;
e = b + len; e = b + len;
while (b<e) { while (b<e) {
...@@ -215,7 +216,6 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr ...@@ -215,7 +216,6 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr
else { else {
value = fiber_result(mrb, a, len); value = fiber_result(mrb, a, len);
} }
fiber_switch_context(mrb, c);
if (vmexec) { if (vmexec) {
c->vmexec = TRUE; c->vmexec = TRUE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment