diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-07-26 13:43:38 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-07-26 13:43:38 +0000 |
commit | 3084f43047fcb3cce12f0e11d41fc2abfbadb824 (patch) | |
tree | 94dde86ea901f22b9f542de952d48d05dbc57499 /gc.c | |
parent | 63e9325781221216e72966637c75d41ef98a7be9 (diff) | |
download | ruby-3084f43047fcb3cce12f0e11d41fc2abfbadb824.tar.gz |
gc.c: running finalizer state
* gc.c (run_finalizer): make saved running finalizer state
volatile to ensure not to be clobbered by longjmp.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55759 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'gc.c')
-rw-r--r-- | gc.c | 32 |
1 files changed, 20 insertions, 12 deletions
@@ -2706,26 +2706,34 @@ run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table) { long i; int status; - const int safe = rb_safe_level(); - const VALUE errinfo = rb_errinfo(); - const VALUE objid = nonspecial_obj_id(obj); + volatile struct { + VALUE errinfo; + VALUE objid; + long finished; + int safe; + } saved; rb_thread_t *const th = GET_THREAD(); - volatile long finished = 0; +#define RESTORE_FINALIZER() (\ + rb_set_safe_level_force(saved.safe), \ + rb_set_errinfo(saved.errinfo)) + + saved.safe = rb_safe_level(); + saved.errinfo = rb_errinfo(); + saved.objid = nonspecial_obj_id(obj); + saved.finished = 0; TH_PUSH_TAG(th); status = TH_EXEC_TAG(); if (status) { - ++finished; /* skip failed finalizer */ - rb_set_safe_level_force(safe); - rb_set_errinfo(errinfo); + ++saved.finished; /* skip failed finalizer */ } - for (i = finished; i<RARRAY_LEN(table); i++) { - finished = i; - run_single_final(RARRAY_AREF(table, i), objid); - rb_set_safe_level_force(safe); - rb_set_errinfo(errinfo); + for (i = saved.finished; + RESTORE_FINALIZER(), i<RARRAY_LEN(table); + saved.finished = ++i) { + run_single_final(RARRAY_AREF(table, i), saved.objid); } TH_POP_TAG(); +#undef RESTORE_FINALIZER } static void |