Bug #10443
closedForking with contended mutex held can lead to deadlock in child process upon unlock
Description
If a Ruby thread calls Process.fork
while holding a Mutex (for example, within a Mutex#synchronize
block) that is also concurrently being contended for by a background thread, the thread in the child process will occasionally be unable to unlock the mutex it was holding at the time of the fork, and will hang under rb_mutex_unlock_th
when attempting to acquire mutex->lock
.
I've been able to reproduce this on Ruby 2.1.1 - 2.1.3 and 2.2.0-preview1 (haven't tried elsewhere yet).
The attached test case demonstrates the issue, although it can take up to 20 minutes to hit a reproducing case. The test case will print one '.' each time it forks. Once it stops printing dots, it has hit this bug (the parent process is stuck in a call to Process.wait
, and the child is stuck in rb_mutex_unlock_th
).
The test case consists of a global lock that is contended for by 10 background threads, in addition to the main thread, which acquires it, forks, and then releases it.
Files