Issue #11384 has been updated by Shugo Maeda.


Eric Wong wrote:
> Eric Wong <normalperson / yhbt.net> wrote:
>  > Currently testing this in a loop:
>  > http://80x24.org/spew/m/94541be0225540e34f0196e9754ae0eb5c07a4b7.txt
>  
>  Nope, the original failure still happens with this, so there's
>  some other place where we're racing :<

TestAutoload#test_threaded_accessing_constant has failed often since r52139,
and it seems to be the same problem.
I could reproduce the problem easily by the following script:

```
require "tempfile"

Tempfile.create(['autoload', '.rb']) {|file|
  file.puts 'sleep(0.5); class AutoloadTest; X = 1; end'
  file.close
  1.upto(Float::INFINITY) do |i|
    p i
    autoload(:AutoloadTest, file.path)
    begin
      t1 = Thread.new { ::AutoloadTest::X }
      t2 = Thread.new { ::AutoloadTest::X }
      [t1, t2].each(&:join)
    ensure
      if Object.const_defined?(:AutoloadTest)
        Object.send(:remove_const, :AutoloadTest)
        $".pop
      end
    end
  end
}
```

The script causes an error within 100 times on My Ubuntu 14.04 box,
but it runs over 10,000 times with your patch.

Your patch looks good to me, and at least it solves the race condition
of autoload_require(), even if there's still another race condition.
Why don't you commit it?


----------------------------------------
Bug #11384: multi-threaded autoload sometimes fails
https://bugs.ruby-lang.org/issues/11384#change-54616

* Author: Eric Wong
* Status: Open
* Priority: Normal
* Assignee: 
* ruby -v: trunk r51319
* Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN
----------------------------------------
~~~
I get this failure once in a blue moon:

#8 test_autoload.rb:46:in `<top (required)>':
     open("zzz.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"}
     autoload :ZZZ, "./zzz.rb"
     t1 = Thread.new {ZZZ.ok}
     t2 = Thread.new {ZZZ.ok}
     [t1.value, t2.value].join
  #=> "" (expected "okok")
stderr output is not empty
   bootstraptest.tmp.rb:5:in `block in <main>': uninitialized constant ZZZ (Name
+Error)
test_autoload.rb        FAIL 1/8
FAIL 1/1010 tests failed


It is a very rare failure, I extracted it into a standalone script and
it took over 500,000 runs to hit it:

unless test(?e, "zzz.rb")
  open("zzz.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"}
end
autoload :ZZZ, "./zzz.rb"
t1 = Thread.new {ZZZ.ok}
t2 = Thread.new {ZZZ.ok}
[t1.value, t2.value].join
~~~

I'll work on this when I find time, but maybe somebody else can look at it
sooner.  I'm not sure if it affects older versions.




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