summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@ruby-lang.org>2020-09-18 17:50:27 (GMT)
committerAaron Patterson <aaron.patterson@gmail.com>2020-09-18 19:31:54 (GMT)
commit1a9dd31910699c7cd69f2a84c94af20eacd5875c (patch)
tree7e5a8225cb2b8697de2d1ccb29333e8f14817398
parent6dd257ed1e54f36deb3e33db12ce9131fdea3b90 (diff)
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.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/3556
-rw-r--r--gc.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/gc.c b/gc.c
index 4b0fd06..eff5486 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);