Project

General

Profile

Actions

Bug #10443

closed

Forking with contended mutex held can lead to deadlock in child process upon unlock

Added by benweint (Ben Weintraub) about 10 years ago. Updated over 5 years ago.

Status:
Closed
Target version:
-
ruby -v:
ruby 2.1.3p242 (2014-09-19 revision 47630) [x86_64-darwin13.0]
[ruby-core:65950]

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

rb-mutex-unlock-fork-test.rb (372 Bytes) rb-mutex-unlock-fork-test.rb benweint (Ben Weintraub), 10/28/2014 03:41 PM
rb-mutex-unlock-fork-test.rb (339 Bytes) rb-mutex-unlock-fork-test.rb benweint (Ben Weintraub), 10/28/2014 07:03 PM
0001-thread.c-reinitialize-keeping-mutexes-on-fork.patch (3.06 KB) 0001-thread.c-reinitialize-keeping-mutexes-on-fork.patch normalperson (Eric Wong), 10/28/2014 09:52 PM
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0