From: John Carter Date: 2009-05-15T12:10:53+09:00 Subject: BUG: "Mutual join" deadlock detection faulty in 1.8.6 and 1.8.7 --Boundary_(ID_Ov+VN8ymNwbZBNSZrpofOw) Content-type: TEXT/PLAIN; charset=ISO-8859-15; format=flowed Content-transfer-encoding: 8BIT I tried submitting this at http://redmine.ruby-lang.org/projects/ruby-186/issues/new but it said "� Mailing list � can't be blank" but wouldn't let me fill in anything in that field. If a third thread is involved, the code in eval.c in function rb_thread_join0 to detect a mutual join dead lock is faulty. This effects ruby 1.8.6 p368 and ruby 1.8.7 p 160 but not ruby 1.9.1 p 129 What seems to be happening is a sequence like this.... main thread grabs mutex thread two blocks waiting for mutex thread one blocks waiting for mutex and th->join is set to the main thread. the main thread unlocks, which wakes thread two. Thread two now has mutex, thread one is still blocked. the main thread attempts to join thread one, rb_thread_join0 notes that thread one is in a WAIT_JOIN waitfor state AND th->join still points at the main thread and (erroneously) reports deadlock. ruby-1.8.7-p160/eval.c================================================ rb_thread_join0(th, limit) rb_thread_t th; double limit; { enum rb_thread_status last_status = THREAD_RUNNABLE; if (rb_thread_critical) rb_thread_deadlock(); if (!rb_thread_dead(th)) { if (th == curr_thread) rb_raise(rb_eThreadError, "thread 0x%lx tried to join itself", th->thread); if ((th->wait_for & WAIT_JOIN) && th->join == curr_thread) rb_raise(rb_eThreadError, "Thread#join: deadlock 0x%lx - mutual join(0x%lx)", curr_thread->thread, th->thread); ====================================================================== Affected versions. /opt/ruby/ruby-1.8.6-p368/bin/ruby -v ruby 1.8.6 (2009-03-31 patchlevel 368) [i686-linux] /opt/ruby/ruby-1.8.7-p160/bin/ruby -v ruby 1.8.7 (2009-04-08 patchlevel 160) [i686-linux] Here is a test script to trigger it.... =mutual_join_bug.rb============================================================ require 'thread' m = Mutex.new m.lock wt2 = Thread.new do m.lock sleep 2 m.unlock end # Ensure wt2 is waiting on m sleep 0.1 wt1 = Thread.new do m.lock m.unlock end # Ensure wt1 is waiting on m sleep 0.1 # Give it to wt2 m.unlock wt1.join ====================================================================== Output... /opt/ruby/ruby-1.8.7-p160/bin/ruby -w mutual_join_bug.rb mutual_join_bug.rb:24:in `join': Thread#join: deadlock 0xb7daa1bc - mutual join(0xb7d9bc48) (ThreadError) from mutual_join_bug.rb:24 John Carter Phone : (64)(3) 358 6639 Tait Electronics Fax : (64)(3) 359 4632 PO Box 1645 Christchurch Email : john.carter@tait.co.nz New Zealand --Boundary_(ID_Ov+VN8ymNwbZBNSZrpofOw)--