mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
thread_sync.c (mutex_ptr): handle mutexes held by parent threads in children
Mutexes may be held by threads which only exist in the parent process, so their waitqueues may be populated with references to other dead threads. We must reset them at fork. I am a moron for introducing this bug :< [ruby-core:90312] [Bug #15383] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66230 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
e941daa6dd
commit
818f1c65ab
2 changed files with 32 additions and 0 deletions
|
@ -1239,6 +1239,27 @@ q.pop
|
|||
end
|
||||
end if Process.respond_to?(:fork)
|
||||
|
||||
def test_fork_while_parent_locked
|
||||
skip 'needs fork' unless Process.respond_to?(:fork)
|
||||
m = Thread::Mutex.new
|
||||
failures = 0
|
||||
run = true
|
||||
thrs = 50.times.map do
|
||||
Thread.new do
|
||||
while run
|
||||
pid = fork { m.synchronize {} }
|
||||
m.synchronize {}
|
||||
_, st = Process.waitpid2(pid)
|
||||
m.synchronize { failures += 1 } unless st.success?
|
||||
end
|
||||
end
|
||||
end
|
||||
sleep 0.5
|
||||
run = false
|
||||
thrs.each(&:join)
|
||||
assert_equal 0, failures, '[ruby-core:90312] [Bug #15383]'
|
||||
end
|
||||
|
||||
def test_subclass_no_initialize
|
||||
t = Module.new do
|
||||
break eval("class C\u{30b9 30ec 30c3 30c9} < Thread; self; end")
|
||||
|
|
|
@ -45,6 +45,7 @@ typedef struct rb_mutex_struct {
|
|||
rb_thread_t *th;
|
||||
struct rb_mutex_struct *next_mutex;
|
||||
struct list_head waitq; /* protected by GVL */
|
||||
rb_serial_t fork_gen;
|
||||
} rb_mutex_t;
|
||||
|
||||
#if defined(HAVE_WORKING_FORK)
|
||||
|
@ -121,8 +122,18 @@ static rb_mutex_t *
|
|||
mutex_ptr(VALUE obj)
|
||||
{
|
||||
rb_mutex_t *mutex;
|
||||
rb_serial_t fork_gen = GET_VM()->fork_gen;
|
||||
|
||||
TypedData_Get_Struct(obj, rb_mutex_t, &mutex_data_type, mutex);
|
||||
|
||||
if (mutex->fork_gen != fork_gen) {
|
||||
/* forked children can't reach into parent thread stacks */
|
||||
mutex->fork_gen = fork_gen;
|
||||
list_head_init(&mutex->waitq);
|
||||
mutex->next_mutex = 0;
|
||||
mutex->th = 0;
|
||||
}
|
||||
|
||||
return mutex;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue