mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge pull request #6233 from dearblue/fiber-end-free
Free stack memory at end of fiber
This commit is contained in:
@@ -223,7 +223,6 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr
|
||||
return fiber_error(mrb, "attempt to resume the current fiber");
|
||||
}
|
||||
|
||||
fiber_check_cfunc(mrb, c);
|
||||
status = c->status;
|
||||
switch (status) {
|
||||
case MRB_FIBER_TRANSFERRED:
|
||||
@@ -241,6 +240,7 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fiber_check_cfunc(mrb, c);
|
||||
if (resume) {
|
||||
old_c->status = MRB_FIBER_RESUMED;
|
||||
c->prev = mrb->c;
|
||||
@@ -394,8 +394,9 @@ fiber_to_s(mrb_state *mrb, mrb_value self)
|
||||
|
||||
const char *file;
|
||||
int32_t line;
|
||||
const struct RProc *p = f->cxt->cibase->proc;
|
||||
if (f->cxt->status != MRB_FIBER_TERMINATED && !MRB_PROC_CFUNC_P(p) && !MRB_PROC_ALIAS_P(p) &&
|
||||
const struct RProc *p;
|
||||
if (f->cxt->status != MRB_FIBER_TERMINATED &&
|
||||
!MRB_PROC_CFUNC_P(p = f->cxt->cibase->proc) && !MRB_PROC_ALIAS_P(p) &&
|
||||
mrb_debug_get_position(mrb, p->body.irep, 0, &line, &file)) {
|
||||
mrb_str_cat_lit(mrb, s, " ");
|
||||
mrb_str_cat_cstr(mrb, s, file);
|
||||
|
||||
@@ -374,7 +374,45 @@ fiber_terminate(mrb_state *mrb, struct mrb_context *c, mrb_callinfo *ci)
|
||||
{
|
||||
mrb_assert(c != mrb->root_c);
|
||||
|
||||
struct REnv *env = CI_ENV(ci);
|
||||
mrb_assert(env == NULL || MRB_ENV_LEN(env) <= c->stend - ci->stack);
|
||||
|
||||
c->status = MRB_FIBER_TERMINATED;
|
||||
mrb_free(mrb, c->cibase);
|
||||
c->cibase = c->ciend = c->ci = NULL;
|
||||
mrb_value *stack = c->stbase;
|
||||
c->stbase = c->stend = NULL;
|
||||
|
||||
if (!env) {
|
||||
mrb_free(mrb, stack);
|
||||
}
|
||||
else {
|
||||
env->cxt = NULL;
|
||||
|
||||
size_t len = (size_t)MRB_ENV_LEN(env);
|
||||
if (len == 0) {
|
||||
env->stack = NULL;
|
||||
MRB_ENV_CLOSE(env);
|
||||
mrb_free(mrb, stack);
|
||||
}
|
||||
else {
|
||||
mrb_assert(stack == env->stack);
|
||||
mrb_write_barrier(mrb, (struct RBasic*)env);
|
||||
|
||||
// don't call MRB_ENV_CLOSE() before mrb_realloc().
|
||||
// the reason is that env->stack may be freed by mrb_realloc() if MRB_DEBUG + MRB_GC_STRESS are enabled.
|
||||
// realloc() on a freed heap will cause double-free.
|
||||
|
||||
stack = (mrb_value*)mrb_realloc(mrb, stack, len * sizeof(mrb_value));
|
||||
if (mrb_object_dead_p(mrb, (struct RBasic*)env)) {
|
||||
mrb_free(mrb, stack);
|
||||
}
|
||||
else {
|
||||
env->stack = stack;
|
||||
MRB_ENV_CLOSE(env);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* fiber termination should automatic yield or transfer to root */
|
||||
mrb->c = c->prev;
|
||||
|
||||
Reference in New Issue
Block a user