diff options
| author | Luke Gruber <luke.gruber@shopify.com> | 2025-08-18 10:47:40 -0400 |
|---|---|---|
| committer | John Hawthorn <john@hawthorn.email> | 2025-09-25 15:29:47 -0700 |
| commit | 62430c19c9f1ab49429cebe65f30588472648c95 (patch) | |
| tree | f419d7e74565ea50dd8e92c6cbce890511363f5d /thread.c | |
| parent | 50393d1ada756fa03febb6566b6820bb1a37036c (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.c | 2 |
1 files changed, 1 insertions, 1 deletions
@@ -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); } |
