summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-07-26 13:43:38 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-07-26 13:43:38 +0000
commit3084f43047fcb3cce12f0e11d41fc2abfbadb824 (patch)
tree94dde86ea901f22b9f542de952d48d05dbc57499
parent63e9325781221216e72966637c75d41ef98a7be9 (diff)
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
-rw-r--r--ChangeLog5
-rw-r--r--gc.c32
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