summaryrefslogtreecommitdiff
path: root/gc.c
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2024-02-29 09:32:10 -0500
committerPeter Zhu <peter@peterzhu.ca>2024-02-29 09:37:38 -0500
commitd5bca0668c6006e0e155d6d293ec3d9b9b2c386b (patch)
treed5cae05ad33b5230910a31621ad65f6775a412fb /gc.c
parent1a6a7c699c4f66396d3f314423fee515ab8b4b19 (diff)
Unset FL_FINALIZE before running the finalizer
The finalizer could trigger a GC, so FL_FINALIZE could get out of sync with the finalizer table.
Diffstat (limited to 'gc.c')
-rw-r--r--gc.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/gc.c b/gc.c
index 1d7500fc10..56ef075c5a 100644
--- a/gc.c
+++ b/gc.c
@@ -4046,8 +4046,8 @@ rb_gc_copy_finalizer(VALUE dest, VALUE obj)
if (st_lookup(finalizer_table, obj, &data)) {
table = (VALUE)data;
st_insert(finalizer_table, dest, table);
+ FL_SET(dest, FL_FINALIZE);
}
- FL_SET(dest, FL_FINALIZE);
}
static VALUE
@@ -4117,6 +4117,7 @@ run_final(rb_objspace_t *objspace, VALUE zombie)
st_data_t key = (st_data_t)zombie;
if (FL_TEST_RAW(zombie, FL_FINALIZE)) {
+ FL_UNSET(zombie, FL_FINALIZE);
st_data_t table;
if (st_delete(finalizer_table, &key, &table)) {
run_finalizer(objspace, zombie, (VALUE)table);
@@ -4302,8 +4303,9 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace)
st_foreach(finalizer_table, force_chain_object, (st_data_t)&list);
while (list) {
struct force_finalize_list *curr = list;
- run_finalizer(objspace, curr->obj, curr->table);
+
FL_UNSET(curr->obj, FL_FINALIZE);
+ run_finalizer(objspace, curr->obj, curr->table);
st_data_t obj = (st_data_t)curr->obj;
st_delete(finalizer_table, &obj, 0);