From 3084f43047fcb3cce12f0e11d41fc2abfbadb824 Mon Sep 17 00:00:00 2001 From: nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> Date: Tue, 26 Jul 2016 13:43:38 +0000 Subject: [PATCH] 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 --- ChangeLog | 5 +++++ gc.c | 32 ++++++++++++++++++++------------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 01fb53e011..551d9ddccc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Tue Jul 26 22:43:36 2016 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * gc.c (run_finalizer): make saved running finalizer state + volatile to ensure not to be clobbered by longjmp. + Tue Jul 26 19:26:00 2016 Koichi Sasada <ko1@atdot.net> * vm_insnhelper.c: introduce rb_vm_pop_frame() and use it diff --git a/gc.c b/gc.c index f8a677ed8b..f3bfe00fbf 100644 --- a/gc.c +++ b/gc.c @@ -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