From 1a9dd31910699c7cd69f2a84c94af20eacd5875c Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 18 Sep 2020 10:50:27 -0700 Subject: [PATCH] Pin values in the finalizer table When finalizers run (in `rb_objspace_call_finalizer`) the table is copied to a linked list that is not managed by the GC. If compaction runs, the references in the linked list can go bad. Finalizer table shouldn't be used frequently, so lets pin references in the table so that the linked list in `rb_objspace_call_finalizer` is safe. --- gc.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/gc.c b/gc.c index 4b0fd06bfc..eff5486353 100644 --- a/gc.c +++ b/gc.c @@ -5046,11 +5046,19 @@ mark_set(rb_objspace_t *objspace, st_table *tbl) st_foreach(tbl, mark_key, (st_data_t)objspace); } +static int +pin_value(st_data_t key, st_data_t value, st_data_t data) +{ + rb_objspace_t *objspace = (rb_objspace_t *)data; + gc_mark_and_pin(objspace, (VALUE)value); + return ST_CONTINUE; +} + static void mark_finalizer_tbl(rb_objspace_t *objspace, st_table *tbl) { if (!tbl) return; - st_foreach(tbl, mark_value, (st_data_t)objspace); + st_foreach(tbl, pin_value, (st_data_t)objspace); } void @@ -7846,11 +7854,6 @@ gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj) case T_RATIONAL: case T_NODE: case T_CLASS: - if (FL_TEST(obj, FL_FINALIZE)) { - if (st_is_member(finalizer_table, obj)) { - return FALSE; - } - } return RVALUE_MARKED(obj) && !RVALUE_PINNED(obj); default: @@ -8748,7 +8751,6 @@ gc_update_references(rb_objspace_t * objspace) gc_update_tbl_refs(objspace, objspace->obj_to_id_tbl); gc_update_table_refs(objspace, objspace->id_to_obj_tbl); gc_update_table_refs(objspace, global_symbols.str_sym); - gc_update_table_refs(objspace, finalizer_table); } static VALUE type_sym(size_t type);