summaryrefslogtreecommitdiff
path: root/thread.c
diff options
context:
space:
mode:
authorLuke Gruber <luke.gruber@shopify.com>2025-08-18 10:47:40 -0400
committerJohn Hawthorn <john@hawthorn.email>2025-09-25 15:29:47 -0700
commit62430c19c9f1ab49429cebe65f30588472648c95 (patch)
treef419d7e74565ea50dd8e92c6cbce890511363f5d /thread.c
parent50393d1ada756fa03febb6566b6820bb1a37036c (diff)
Properly unlock locked mutexes on thread cleanup.
Mutexes were being improperly unlocked on thread cleanup. This bug was introduced in 050a8954395. We must keep a reference from the mutex to the thread, because if the fiber is collected before the mutex is, then we cannot unlink it from the thread in `mutex_free`. If it's not unlinked from the the thread when it's freed, it causes bugs in `rb_thread_unlock_all_locking_mutexes`. We now mark the fiber when a mutex is locked, and the thread is marked as well. However, a fiber can still be freed in the same GC cycle as the mutex, so the reference to the thread is still needed. The reason we need to mark the fiber is that `mutex_owned_p()` has an ABA issue where if the fiber is collected while it's locked, a new fiber could be allocated at the same memory address and we could get false positives. Fixes [Bug #21342] Co-authored-by: John Hawthorn <john@hawthorn.email>
Diffstat (limited to 'thread.c')
-rw-r--r--thread.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/thread.c b/thread.c
index bab615b9ed..5556100102 100644
--- a/thread.c
+++ b/thread.c
@@ -442,7 +442,7 @@ rb_threadptr_unlock_all_locking_mutexes(rb_thread_t *th)
th->keeping_mutexes = mutex->next_mutex;
// rb_warn("mutex #<%p> was not unlocked by thread #<%p>", (void *)mutex, (void*)th);
-
+ VM_ASSERT(mutex->fiber);
const char *error_message = rb_mutex_unlock_th(mutex, th, mutex->fiber);
if (error_message) rb_bug("invalid keeping_mutexes: %s", error_message);
}