summaryrefslogtreecommitdiff
path: root/gc.c
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2021-07-23 00:32:09 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2021-07-23 12:01:15 +0900
commitfc4dd45d0142221880d1b2c9b54dee0597be2b78 (patch)
treef0defbf6005cabb4fb05a0e51e620fb2ad21f49e /gc.c
parent63e5f4df387ba24b561c304c56a2f4357de15fe3 (diff)
Show exception in finalizer [Feature #17798]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4670
Diffstat (limited to 'gc.c')
-rw-r--r--gc.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/gc.c b/gc.c
index 97a4c8b521..61ff6abece 100644
--- a/gc.c
+++ b/gc.c
@@ -3988,6 +3988,16 @@ run_single_final(VALUE cmd, VALUE objid)
}
static void
+warn_exception_in_finalizer(rb_execution_context_t *ec, VALUE final)
+{
+ if (final != Qundef) {
+ VALUE errinfo = ec->errinfo;
+ rb_warn("Exception in finalizer %+"PRIsVALUE, final);
+ rb_ec_error_print(ec, errinfo);
+ }
+}
+
+static void
run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table)
{
long i;
@@ -3995,6 +4005,7 @@ run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table)
volatile struct {
VALUE errinfo;
VALUE objid;
+ VALUE final;
rb_control_frame_t *cfp;
long finished;
} saved;
@@ -4007,16 +4018,18 @@ run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table)
saved.objid = rb_obj_id(obj);
saved.cfp = ec->cfp;
saved.finished = 0;
+ saved.final = Qundef;
EC_PUSH_TAG(ec);
state = EC_EXEC_TAG();
if (state != TAG_NONE) {
++saved.finished; /* skip failed finalizer */
+ warn_exception_in_finalizer(ec, ATOMIC_VALUE_EXCHANGE(saved.final, Qundef));
}
for (i = saved.finished;
RESTORE_FINALIZER(), i<RARRAY_LEN(table);
saved.finished = ++i) {
- run_single_final(RARRAY_AREF(table, i), saved.objid);
+ run_single_final(saved.final = RARRAY_AREF(table, i), saved.objid);
}
EC_POP_TAG();
#undef RESTORE_FINALIZER