Show exception in finalizer [Feature #17798]

This commit is contained in:
Nobuyoshi Nakada 2021-07-23 00:32:09 +09:00
Родитель 63e5f4df38
Коммит fc4dd45d01
2 изменённых файлов: 21 добавлений и 1 удалений

15
gc.c
Просмотреть файл

@ -3987,6 +3987,16 @@ run_single_final(VALUE cmd, VALUE objid)
return rb_check_funcall(cmd, idCall, 1, &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)
{
@ -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

Просмотреть файл

@ -161,6 +161,13 @@ End
END
end
def test_exception_in_finalizer
assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}", [], /finalizing \(RuntimeError\)/)
begin;
ObjectSpace.define_finalizer(Object.new) {raise "finalizing"}
end;
end
def test_each_object
klass = Class.new
new_obj = klass.new