Project

General

Profile

Bug #15508

Mutex recursive lock error when combined with Thread#raise

Added by larskanis (Lars Kanis) 4 months ago. Updated 3 days ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.6.0p0 (2018-12-25 revision 66547) [x86_64-linux]
[ruby-core:90899]

Description

This is another issue I noticed with Eventbox:

This script triggers sporadic error deadlock; recursive locking (ThreadError):

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:

$  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:0x0000560244102650@recursive-lock-error.rb: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.

History

Updated by larskanis (Lars Kanis) 3 days ago

I verified that this issue is fixed by PR #2131.

Also available in: Atom PDF