From 52e571fa72debcd764765775bd1b76ee87e36d2d Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Tue, 4 Apr 2023 23:55:43 -0400 Subject: [PATCH] Ensure ruby_xfree won't segfault if called after vm_destruct [Bug #19580] The real-world scenario motivating this change is libxml2's pthread code which uses `pthread_key_create` to set up a destructor that is called at thread exit to free thread-local storage. There is a small window of time -- after ruby_vm_destruct but before the process exits -- in which a pthread may exit and the destructor is called, leading to a segfault. Please note that this window of time may be relatively large if `atexit` is being used. --- gc.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/gc.c b/gc.c index 6f68bbbea7..0a0572e208 100644 --- a/gc.c +++ b/gc.c @@ -12581,8 +12581,16 @@ ruby_xrealloc2_body(void *ptr, size_t n, size_t size) void ruby_sized_xfree(void *x, size_t size) { - if (x) { - objspace_xfree(&rb_objspace, x, size); + if (LIKELY(x)) { + /* It's possible for a C extension's pthread destructor function set by pthread_key_create + * to be called after ruby_vm_destruct and attempt to free memory. Fall back to mimfree in + * that case. */ + if (LIKELY(GET_VM())) { + objspace_xfree(&rb_objspace, x, size); + } + else { + ruby_mimfree(x); + } } }