restore the stack pointer on finalizer

When error on finalizer, the exception will be ignored.
To restart the code, we need to restore the stack pointer.

fix [Bug #20042]
This commit is contained in:
Koichi Sasada 2023-12-19 17:32:19 +09:00
parent 96e4f42b3d
commit f9a48548cf
2 changed files with 13 additions and 0 deletions

4
gc.c
View File

@ -4426,16 +4426,20 @@ run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table)
VALUE objid;
VALUE final;
rb_control_frame_t *cfp;
VALUE *sp;
long finished;
} saved;
rb_execution_context_t * volatile ec = GET_EC();
#define RESTORE_FINALIZER() (\
ec->cfp = saved.cfp, \
ec->cfp->sp = saved.sp, \
ec->errinfo = saved.errinfo)
saved.errinfo = ec->errinfo;
saved.objid = rb_obj_id(obj);
saved.cfp = ec->cfp;
saved.sp = ec->cfp->sp;
saved.finished = 0;
saved.final = Qundef;

View File

@ -810,6 +810,15 @@ class TestGc < Test::Unit::TestCase
obj = nil
end
end;
assert_normal_exit "#{<<~"begin;"}\n#{<<~'end;'}", '[Bug #20042]'
begin;
def (f = Object.new).call = nil # missing ID
o = Object.new
ObjectSpace.define_finalizer(o, f)
o = nil
GC.start
end;
end
def test_object_ids_never_repeat