diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-04-25 17:25:48 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-04-25 17:25:48 +0900 |
| commit | aa8e490fd54bc7c62e591edc349c0dcb5cc572a9 (patch) | |
| tree | 250e4922c47bc2b110af3a2cbb7e10943a8beb32 /src/gc.c | |
| parent | 88cd807379152ea3fec5f534e5f4d6ebebd53982 (diff) | |
| download | mruby-aa8e490fd54bc7c62e591edc349c0dcb5cc572a9.tar.gz mruby-aa8e490fd54bc7c62e591edc349c0dcb5cc572a9.zip | |
Prevent GC during `each_object`; fix #3616
Diffstat (limited to 'src/gc.c')
| -rw-r--r-- | src/gc.c | 32 |
1 files changed, 29 insertions, 3 deletions
@@ -17,6 +17,7 @@ #include <mruby/variable.h> #include <mruby/gc.h> #include <mruby/error.h> +#include <mruby/throw.h> /* = Tri-color Incremental Garbage Collection @@ -1162,7 +1163,7 @@ mrb_incremental_gc(mrb_state *mrb) { mrb_gc *gc = &mrb->gc; - if (gc->disabled) return; + if (gc->disabled || gc->iterating) return; GC_INVOKE_TIME_REPORT("mrb_incremental_gc()"); GC_TIME_START; @@ -1202,7 +1203,7 @@ mrb_full_gc(mrb_state *mrb) { mrb_gc *gc = &mrb->gc; - if (gc->disabled) return; + if (gc->disabled || gc->iterating) return; GC_INVOKE_TIME_REPORT("mrb_full_gc()"); GC_TIME_START; @@ -1508,7 +1509,32 @@ gc_each_objects(mrb_state *mrb, mrb_gc *gc, mrb_each_object_callback *callback, void mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, void *data) { - gc_each_objects(mrb, &mrb->gc, callback, data); + mrb_bool iterating = mrb->gc.iterating; + + mrb_full_gc(mrb); + mrb->gc.iterating = TRUE; + if (iterating) { + gc_each_objects(mrb, &mrb->gc, callback, data); + } + else { + struct mrb_jmpbuf *prev_jmp = mrb->jmp; + struct mrb_jmpbuf c_jmp; + + MRB_TRY(&c_jmp) { + mrb->jmp = &c_jmp; + gc_each_objects(mrb, &mrb->gc, callback, data); + mrb->jmp = prev_jmp; + mrb->gc.iterating = iterating; + } MRB_CATCH(&c_jmp) { + mrb->jmp = prev_jmp; + mrb->gc.iterating = iterating; + if (mrb->exc) { + mrb_value exc = mrb_obj_value(mrb->exc); + mrb->exc = NULL; + mrb_exc_raise(mrb, exc); + } + } MRB_END_EXC(&c_jmp); + } } #ifdef GC_TEST |
