From: headius@... Date: 2016-09-22T17:39:26+00:00 Subject: [ruby-core:77362] [Ruby trunk Bug#12688] Thread unsafety in autoload Issue #12688 has been updated by Charles Nutter. > $".pop would be needed to clear bar.rb in loaded features. > I don't get NameError after adding $".pop. But why does it work for a while and then stop working? There still seems to be a threading issue here. Here's my modified script, with the confirmation dots moved after the constant lookup and Thread.abort_on_exception = true: ```ruby Thread.abort_on_exception = true loop do class Foo autoload :Bar, 'bar.rb' end go = false threads = (1..50).map {Thread.new { 1 until go; Foo.const_get(:Bar); print '.' }} go = true threads.each(&:join) puts self.class.send :remove_const, :Foo end ``` It successfully runs for less than 50 dots, and then one of the threads errors out. I don't think it should. Note also this is not even getting to a second iteration; the first iteration of the outer loop fails. If I add `$".pop` after `remove_const`, it does run for longer...but it still produces a NameError for me. ``` $ ruby23 -I. blah.rb .................................................. .................................................. .................................................. .................................................. .................................................. blah.rb:9:in `const_get': uninitialized constant Foo::Bar (NameError) Did you mean? Foo::Bar from blah.rb:9:in `block (3 levels) in
' ``` ---------------------------------------- Bug #12688: Thread unsafety in autoload https://bugs.ruby-lang.org/issues/12688#change-60605 * Author: Charles Nutter * Status: Open * Priority: Normal * Assignee: * ruby -v: 2.3.0 * Backport: 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN ---------------------------------------- I need clarification here. I expected, based on Ruby's assertion that autoloads are thread-safe, that the following code would never error. Instead, it gets a couple iterations in and raises NameError: ```ruby loop do class Foo autoload :Bar, 'bar.rb' end go = false threads = (1..50).map {Thread.new { 1 until go; print '.'; Foo.const_get(:Bar) }} go = true threads.each(&:join) puts self.class.send :remove_const, :Foo end ``` And the output with Ruby 2.3.0: ``` $ ruby23 -I. autoload_breaker.rb .................................................. ..................................................autoload_breaker.rb:7:in `const_get': uninitialized constant Foo::Bar (NameError) Did you mean? Foo::Bar from autoload_breaker.rb:7:in `block (3 levels) in
' ``` Is there something wrong with my script? Is my expectation incorrect? -- https://bugs.ruby-lang.org/ Unsubscribe: