summaryrefslogtreecommitdiffhomepage
path: root/src/proc.c
diff options
context:
space:
mode:
authorKouhei Sutou <[email protected]>2015-06-29 14:39:30 +0900
committerKouhei Sutou <[email protected]>2015-06-29 14:39:30 +0900
commit52db92de53a9af1adbac9e116bd19aeecd2485c1 (patch)
tree30062490e31cfec9c462050cefe636a134e2ecc0 /src/proc.c
parentb0ec992d4170ed06bd96020edbc889a224b23be1 (diff)
downloadmruby-52db92de53a9af1adbac9e116bd19aeecd2485c1.tar.gz
mruby-52db92de53a9af1adbac9e116bd19aeecd2485c1.zip
Fix a crash bug when GC is ran while creating a proc with env
mrb_proc_new_cfunc_with_env() allocates RProc with RProc::env as NULL then allocates REnv and sets it to RProc::env of the allocated RProc. If incremental GC is ran before "allocates REnv and sets it to RProc::env of the allocated RProc", the allocated RProc's GC status is "marked" (Black) and the allocated REnv's GC status is "unmarked" (White). The next incremental GC sweeps the allocated REnv without re-marking the allocated RProc. Because the RProc is Black and the REnv is White. We need to implement write barrier for the case. We can force to cause the above situation by the following patch: diff --git a/src/proc.c b/src/proc.c index f98998f..4f4e25c 100644 --- a/src/proc.c +++ b/src/proc.c @@ -92,6 +92,7 @@ mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t func, mrb_int argc, const struct REnv *e; int i; + mrb_incremental_gc(mrb); p->env = e = env_new(mrb, argc); MRB_ENV_UNSHARE_STACK(e); e->stack = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * argc); With this patch, "rake test" causes segmentation fault.
Diffstat (limited to 'src/proc.c')
-rw-r--r--src/proc.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/src/proc.c b/src/proc.c
index f98998f68..8a2b6bbb6 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -93,6 +93,7 @@ mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t func, mrb_int argc, const
int i;
p->env = e = env_new(mrb, argc);
+ mrb_field_write_barrier(mrb, (struct RBasic *)p, (struct RBasic *)p->env);
MRB_ENV_UNSHARE_STACK(e);
e->stack = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * argc);
if (argv) {