Project

General

Profile

Bug #15360

"ThreadError: deadlock; recursive locking" error when recursive lock shouldn't be possible

Added by brockspratlen (Brock Spratlen) 6 months ago. Updated about 1 month ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-darwin17]
[ruby-core:90170]

Description

I think I've discovered a Ruby bug, possibly introduced in 2.5.

I've attached a reproduction script; running it on Ruby 2.5.0+ (including previews of 2.6.0) seems to always produce a flood of printed ThreadError: deadlock; recursive locking exceptions, even though the reproduction code doesn't appear to do any recursive locking.

Running the same script on Ruby 2.4.5 doesn't produce any ThreadError: deadlock; recursive locking exceptions. I've run the script several times on Ruby 2.4.5, I simply can't reproduce the raising of ThreadError: deadlock; recursive locking with this script on 2.4.5.

Curiously, removing the puts e.class on line 24 causes the bug to go away: ThreadError: deadlock; recursive locking never gets raised regardless of which Ruby version I'm running. Given this oddity, I can't help but think the issue is something around writing to stdout. This change in particular looks suspect: https://bugs.ruby-lang.org/issues/9323

Thank you!
Brock


Files

deadlock_test.rb (556 Bytes) deadlock_test.rb Run with "ruby deadlock_test.rb" brockspratlen (Brock Spratlen), 11/29/2018 06:09 PM

History

#1

Updated by brockspratlen (Brock Spratlen) 6 months ago

  • ruby -v changed from 2.5.3 to ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-darwin17]
#2

Updated by brockspratlen (Brock Spratlen) 6 months ago

  • Description updated (diff)

Updated by Anonymous about 2 months ago

Is there a plan to fix this? We have been noticing this bug occasionally in production.

Updated by wanabe (_ wanabe) about 1 month ago

git bisect shows the problem occurs frequently since r58604.
But I don't know it can occur before the commit.

https://bugs.ruby-lang.org/projects/ruby-trunk/repository/trunk/revisions/66489/entry/thread_sync.c#L267
do_mutex_lock() releases GVL with native_sleep(th, timeout).
The mutex may be released and the thread may be interrupted around the same time.
If so, RUBY_VM_CHECK_INTS_BLOCKING(th->ec) will raise an exception, after locking mutex.

Also available in: Atom PDF