[ruby-core:93056] [Ruby trunk Bug#15508] Mutex recursive lock error when combined with Thread#raise

From: merch-redmine@...
Date: 2019-06-11 22:52:28 UTC
List: ruby-core #93056
Issue #15508 has been updated by jeremyevans0 (Jeremy Evans).

Status changed from Open to Closed

Fix committed at commit:c1d78a7f0ece2004822193a0c1f1fd3dc38c2fdf

----------------------------------------
Bug #15508: Mutex recursive lock error when combined with Thread#raise
https://bugs.ruby-lang.org/issues/15508#change-78460

* Author: larskanis (Lars Kanis)
* Status: Closed
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: ruby 2.6.0p0 (2018-12-25 revision 66547) [x86_64-linux]
* Backport: 2.4: UNKNOWN, 2.5: UNKNOWN, 2.6: UNKNOWN
----------------------------------------
This is another issue I noticed with [Eventbox](https://github.com/larskanis/eventbox):

This script triggers sporadic error `deadlock; recursive locking (ThreadError)`:
```ruby
Thread.abort_on_exception = true

class Stop < RuntimeError
end

def go
  mutex = Mutex.new

  ths = 10.times.map do
    Thread.handle_interrupt(Exception => :never) do
      Thread.new do
        begin
          Thread.handle_interrupt(Stop => :on_blocking) do
            mutex.synchronize{}
            sleep
          end
        rescue Stop
        end
        mutex.synchronize{}
      end
    end
  end

  ths.each do |th|
    th.raise Stop
  end

  ths.each(&:join)
end

100.times do
  go
end
```

The program must be started in a loop, since it doesn't fail always. But if called in a while loop, typically aborts after some seconds like so:
```sh
$  while (ruby -d --disable-gems recursive-lock-error.rb ); do true; done
[...]
Exception `Stop' at recursive-lock-error.rb:15 - Stop
Exception `Stop' at recursive-lock-error.rb:15 - Stop
Exception `Stop' at recursive-lock-error.rb:14 - Stop
Exception `Stop' at recursive-lock-error.rb:14 - Stop
Exception `Stop' at recursive-lock-error.rb:14 - Stop
Exception `Stop' at recursive-lock-error.rb:14 - Stop
Exception `Stop' at recursive-lock-error.rb:15 - Stop
Exception `Stop' at recursive-lock-error.rb:14 - Stop
Exception `ThreadError' at recursive-lock-error.rb:19 - deadlock; recursive locking
#<Thread:[email protected]:11 run> terminated with exception (report_on_exception is true):
Traceback (most recent call last):
	1: from recursive-lock-error.rb:19:in `block (3 levels) in go'
recursive-lock-error.rb:19:in `synchronize': deadlock; recursive locking (ThreadError)
```

According to my analysis it happens, that the `Stop` exception is sometimes delivered while `Mutex#lock` is running, but the mutex ownership isn't properly cleared. The next call to `Mutex#lock` then fails with `recursive locking` error.

This issue is present on ruby-2.5.3 and 2.6.0. Ruby-2.4 seems to be unaffected.




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

Unsubscribe: <mailto:[email protected]?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

In This Thread

Prev Next