Project

General

Profile

Actions

Bug #15599

closed

Mixing autoload and require causes deadlock and incomplete definition.

Bug #15599: Mixing autoload and require causes deadlock and incomplete definition.

Added by akr (Akira Tanaka) over 7 years ago. Updated 5 days ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 2.7.0dev (2019-02-11 trunk 67049) [x86_64-linux]
[ruby-core:91519]

Description

I found that mixing autoload and require causes deadlock and incomplete definition.

% cat a.rb 
class A
  def a1() end
end
% cat base.rb 
autoload :A, './a'

t1 = Thread.new { p A.instance_methods(false) }
t2 = Thread.new { require './a' }

t1.join
t2.join
% ruby base.rb 
Traceback (most recent call last):
	1: from base.rb:6:in `<main>'
base.rb:6:in `join': No live threads left. Deadlock? (fatal)
3 threads, 3 sleeps current:0x000055cc6943fde0 main thread:0x000055cc6935f4b0
* #<Thread:0x000055cc6938f190 sleep_forever>
   rb_thread_t:0x000055cc6935f4b0 native:0x00007f58d256eb40 int:0
   base.rb:6:in `join'
   base.rb:6:in `<main>'
* #<Thread:0x000055cc6968cfc8@base.rb:3 sleep_forever>
   rb_thread_t:0x000055cc69736180 native:0x00007f58ce7b3700 int:0 mutex:0x000055cc6943fde0 cond:1
    depended by: tb_thread_id:0x000055cc6935f4b0
   /home/akr/ruby/o0/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:54:in `require'
   /home/akr/ruby/o0/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:54:in `require'
   base.rb:3:in `block in <main>'
* #<Thread:0x000055cc6968ccd0@base.rb:4 sleep_forever>
   rb_thread_t:0x000055cc6943fde0 native:0x00007f58ce5b1700 int:0
   /tmp/a/a.rb:1:in `<top (required)>'
   /home/akr/ruby/o0/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:54:in `require'
   /home/akr/ruby/o0/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:54:in `require'
   base.rb:4:in `block in <main>'
% ruby base.rb
[:a1]
% ruby base.rb
[]

The last run which prints [] means incomplete definition of A which a1 method is not defined.


Related issues 2 (1 open1 closed)

Related to Ruby - Bug #15598: Deadlock on mutual reference of autoloaded constantsOpenActions
Related to Ruby - Misc #21154: Document or change Module#autoload?Feedbackmame (Yusuke Endoh)Actions

Updated by akr (Akira Tanaka) over 7 years ago Actions #1

  • Related to Bug #15598: Deadlock on mutual reference of autoloaded constants added

Updated by akr (Akira Tanaka) about 1 year ago Actions #2

  • Related to Misc #21154: Document or change Module#autoload? added

Updated by wanabe (_ wanabe) 5 days ago Actions #3 [ruby-core:126355]

  • Status changed from Open to Closed

This issue was fixed between preview 2 and preview 3 of Ruby 3.3.0.

$ cat a.rb
class A
  def a1() end
end
$ cat base.rb 
1000.times do
  fork do
    autoload :A, './a'

    t1 = Thread.new { raise if A.instance_methods(false).size != 1 }
    t2 = Thread.new { require './a' }

    begin
      t1.join
      t2.join
    rescue Exception => e
      exit 1
    end
  end
end
p Process.waitall.map {|_pid, status| status.success? ? :success : :failure }.group_by(&:itself).transform_values(&:size).to_a
puts :fin
$ docker run -it --rm -v.:/work -w/work --env ALL_RUBY_SINCE=3.2.10 rubylang/all-ruby /all-ruby/all-ruby base.rb
ruby-3.2.10         #<Thread:0x00007119bd008e88 base.rb:5 run> terminated with exception (report_on_exception is true):
                    base.rb:5:in `block (3 levels) in <main>': unhandled exception
                    #<Thread:0x00007119bd008e88 base.rb:5 run> terminated with exception (report_on_exception is true):
                    base.rb:5:in `block (3 levels) in <main>': unhandled exception
                    #<Thread:0x00007119bd008e88 base.rb:5 run> terminated with exception (report_on_exception is true):
                    base.rb:5:in `block (3 levels) in <main>': unhandled exception
                    #<Thread:0x00007119bd008e88 base.rb:5 run> terminated with exception (report_on_exception is true):
                    base.rb:5:in `block (3 levels) in <main>': unhandled exception
                    [[:success, 921], [:failure, 79]]
                    fin
ruby-3.2.11         #<Thread:0x00007eb67a448f68 base.rb:5 run> terminated with exception (report_on_exception is true):
                    base.rb:5:in `block (3 levels) in <main>': unhandled exception
                    [[:success, 922], [:failure, 78]]
                    fin
ruby-3.3.0-preview1 #<Thread:0x00007429d36e67e0 base.rb:5 run> terminated with exception (report_on_exception is true):
                    base.rb:5:in `block (3 levels) in <main>': unhandled exception
                    [[:success, 931], [:failure, 69]]
                    fin
ruby-3.3.0-preview2 #<Thread:0x0000751915115f78 base.rb:5 run> terminated with exception (report_on_exception is true):
                    base.rb:5:in `block (3 levels) in <main>': unhandled exception
                    #<Thread:0x0000751915115f78 base.rb:5 run> terminated with exception (report_on_exception is true):
                    base.rb:5:in `block (3 levels) in <main>': unhandled exception
                    #<Thread:0x0000751915115f78 base.rb:5 run> terminated with exception (report_on_exception is true):
                    base.rb:5:in `block (3 levels) in <main>': unhandled exception
                    #<Thread:0x0000751915115f78 base.rb:5 run> terminated with exception (report_on_exception is true):
                    base.rb:5:in `block (3 levels) in <main>': unhandled exception
                    #<Thread:0x0000751915115f78 base.rb:5 run> terminated with exception (report_on_exception is true):
                    base.rb:5:in `block (3 levels) in <main>': unhandled exception
                    #<Thread:0x0000751915115f78 base.rb:5 run> terminated with exception (report_on_exception is true):
                    base.rb:5:in `block (3 levels) in <main>': unhandled exception
                    #<Thread:0x0000751915115f78 base.rb:5 run> terminated with exception (report_on_exception is true):
                    base.rb:5:in `block (3 levels) in <main>': unhandled exception
                    #<Thread:0x0000751915115f78 base.rb:5 run> terminated with exception (report_on_exception is true):
                    base.rb:5:in `block (3 levels) in <main>': unhandled exception
                    [[:success, 904], [:failure, 96]]
                    fin
ruby-3.3.0-preview3 [[:success, 1000]]
                    fin
...
ruby-4.0.6          [[:success, 1000]]
                    fin

I found the commit is be1bbd5b7d40ad863ab35097765d3754726bbd54 == https://bugs.ruby-lang.org/issues/19842.
I don't know why this is the case, but I suspect that the refactoring done to achieve the original goal (M:N threads) had a positive effect.

$ git checkout be1bbd5b7d40ad863ab35097765d3754726bbd54~ && make -j miniruby >/dev/null 2>&1 && ./miniruby base.rb
HEAD is now at 096ee0648e2 Bump ruby/setup-ruby from 1.155.0 to 1.156.0
[[:success, 945], [:failure, 55]]
fin
$ git checkout be1bbd5b7d40ad863ab35097765d3754726bbd54 && make -j miniruby >/dev/null 2>&1 && ./miniruby base.rb
Previous HEAD position was 096ee0648e2 Bump ruby/setup-ruby from 1.155.0 to 1.156.0
HEAD is now at be1bbd5b7d4 M:N thread scheduler for Ractors
[[:success, 1000]]
fin

Actions

Also available in: PDF Atom