summaryrefslogtreecommitdiff
path: root/gc.c
diff options
context:
space:
mode:
authorAlan Wu <XrXr@users.noreply.github.com>2024-01-12 11:30:36 -0500
committerAlan Wu <XrXr@users.noreply.github.com>2024-01-12 13:28:36 -0500
commite59dd7094f281e3167fc8fe29ab0e92e7b66027a (patch)
treeb72f2b6039879fa6b3259b0c57cac6e71015b74d /gc.c
parent0462b1b350b0f86ce4cfebc195fe0f24005d28f4 (diff)
Pass more T_DATA to obj_free() under RUBY_FREE_AT_EXIT
T_DATA without a pointer or free function may still have ivars set on them that need to be freed. The following leaked generic ivars for example: converter = Encoding::Converter.allocate converter.instance_variable_set(:@foo, 1) STACK OF 1 INSTANCE OF 'ROOT LEAK: <malloc in objspace_xmalloc0>': <snip> 12 miniruby 0x10286ec50 ivar_set + 140 variable.c:1850 11 miniruby 0x102876afc generic_ivar_set + 136 variable.c:1668
Diffstat (limited to 'gc.c')
-rw-r--r--gc.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/gc.c b/gc.c
index 0e4dadbdd0..6245e2083b 100644
--- a/gc.c
+++ b/gc.c
@@ -4684,7 +4684,7 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace)
void *poisoned = asan_unpoison_object_temporary(vp);
switch (BUILTIN_TYPE(vp)) {
case T_DATA:
- if (!DATA_PTR(p) || !RANY(p)->as.data.dfree) break;
+ if (!rb_free_at_exit && (!DATA_PTR(p) || !RANY(p)->as.data.dfree)) break;
if (rb_obj_is_thread(vp)) break;
if (rb_obj_is_mutex(vp)) break;
if (rb_obj_is_fiber(vp)) break;