[#67346] Future of test suites for Ruby — Charles Oliver Nutter <headius@...>

I'll try to be brief so we can discuss all this. tl;dr: RubySpec is

19 messages 2015/01/05

[ruby-core:67719] [ruby-trunk - Bug #9432] ThreadError [ Attempt to unlock a mutex which is locked by another thread ]

From: aaron@...
Date: 2015-01-21 08:42:39 UTC
List: ruby-core #67719
Issue #9432 has been updated by Aaron Stone.


In Ruby 1.9.3, thread.rb has Queue.pop defined as:

~~~
183   def pop(non_block=false)
184     @mutex.synchronize{
185       while true
186         if @que.empty?
187           raise ThreadError, "queue empty" if non_block
188           @waiting.push Thread.current
189           @mutex.sleep
190         else
191           return @que.shift
192         end
193       end
194     }
195   end
~~~

In Ruby 2.0, thread.rb has Queue.pop defined as:

~~~
186   def pop(non_block=false)
187     Thread.handle_interrupt(StandardError => :on_blocking) do
188       @mutex.synchronize do
189         while true
190           if @que.empty?
191             if non_block
192               raise ThreadError, "queue empty"
193             else
194               begin
195                 @num_waiting += 1
196                 @cond.wait @mutex
197               ensure
198                 @num_waiting -= 1
199               end
200             end
201           else
202             return @que.shift
203           end
204         end
205       end
206     end
207   end
~~~

The use of ConditionVariable is new in 2.0 vs. 1.9.3, and I think it is causing the problem. In 1.9.3, Queue.push itself walks its @waiting array to find and wake up a thread that will consume the just-pushed element. In 2.0, Queue.push calls @cond.signal which then goes and looks for a thread to wake up.

Ok, here's the most salient difference:
In 1.9.3, Queue.push calls **thread.wakeup** on a consuming thread.
In 2.0, Queue.push calls ConditionVariable.signal calls **thread.run** on a consuming thread.

The difference is that thread.run also executes the scheduler immediately.

In Ruby 2.1 and up, thread.rb does not exist - it appears to be rewritten in C.

----------------------------------------
Bug #9432:  ThreadError [ Attempt to unlock a mutex which is locked by another thread ]
https://bugs.ruby-lang.org/issues/9432#change-51149

* Author: rajesh shanmugam
* Status: Open
* Priority: Normal
* Assignee: 
* ruby -v: 2.0.0
* Backport: 
----------------------------------------
I use ruby-2.0.0-p247. I seem to get this issue frequently in threaded environment. (Sidekiq) 

I am not very sure if it a ruby thread issue as such or something I am doing wrong. If there is any more details you need I would be happy to provide you.

Operating system: Ubuntu

Trace

```
/home/ubuntu/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/thread.rb:188:in `synchronize'
/home/ubuntu/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/thread.rb:188:in `block in pop'
/home/ubuntu/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/thread.rb:187:in `handle_interrupt'
/home/ubuntu/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/thread.rb:187:in `pop'
```

Regards
Rajesh



-- 
https://bugs.ruby-lang.org/

In This Thread

Prev Next