diff options
| author | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-03-27 09:28:37 +0000 |
|---|---|---|
| committer | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-03-27 09:28:37 +0000 |
| commit | a2d63ea2fb84c962abddae877e9493fc57cfce1a (patch) | |
| tree | 4503e0aa911338f50abdcc580a169d56f9f14a9a /test/thread/test_queue.rb | |
| parent | 98e9444b5f33873fa3e8e8cdd4143771b1bc477e (diff) | |
thread_sync.c: avoid reaching across stacks of dead threads
rb_ensure is insufficient cleanup for fork and we must
reinitialize all waitqueues in the child process.
Unfortunately this increases the footprint of ConditionVariable,
Queue and SizedQueue by 8 bytes on 32-bit (16 bytes on 64-bit).
[ruby-core:86316] [Bug #14634]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62934 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'test/thread/test_queue.rb')
| -rw-r--r-- | test/thread/test_queue.rb | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/test/thread/test_queue.rb b/test/thread/test_queue.rb index 4e6c9fa4c9..d69ecf92b2 100644 --- a/test/thread/test_queue.rb +++ b/test/thread/test_queue.rb @@ -565,4 +565,52 @@ class TestQueue < Test::Unit::TestCase puts 'exit' INPUT end + + def test_fork_while_queue_waiting + q = Queue.new + sq = SizedQueue.new(1) + thq = Thread.new { q.pop } + thsq = Thread.new { sq.pop } + Thread.pass until thq.stop? && thsq.stop? + + pid = fork do + exit!(1) if q.num_waiting != 0 + exit!(2) if sq.num_waiting != 0 + exit!(6) unless q.empty? + exit!(7) unless sq.empty? + q.push :child_q + sq.push :child_sq + exit!(3) if q.pop != :child_q + exit!(4) if sq.pop != :child_sq + exit!(0) + end + _, s = Process.waitpid2(pid) + assert_predicate s, :success?, 'no segfault [ruby-core:86316] [Bug #14634]' + + q.push :thq + sq.push :thsq + assert_equal :thq, thq.value + assert_equal :thsq, thsq.value + + sq.push(1) + th = Thread.new { q.pop; sq.pop } + thsq = Thread.new { sq.push(2) } + Thread.pass until th.stop? && thsq.stop? + pid = fork do + exit!(1) if q.num_waiting != 0 + exit!(2) if sq.num_waiting != 0 + exit!(3) unless q.empty? + exit!(4) if sq.empty? + exit!(5) if sq.pop != 1 + exit!(0) + end + _, s = Process.waitpid2(pid) + assert_predicate s, :success?, 'no segfault [ruby-core:86316] [Bug #14634]' + + assert_predicate thsq, :stop? + assert_equal 1, sq.pop + assert_same sq, thsq.value + q.push('restart th') + assert_equal 2, th.value + end if Process.respond_to?(:fork) end |
