From: Yura Sokolov Date: 2011-12-15T21:19:39+09:00 Subject: [ruby-core:41678] [ruby-trunk - Bug #5754] Double require bug in 1.9.3 Issue #5754 has been updated by Yura Sokolov. > it doesn't see an entry in the loading table even though t2 is currently loading the file Has it something common with #5727 ? ---------------------------------------- Bug #5754: Double require bug in 1.9.3 http://redmine.ruby-lang.org/issues/5754 Author: Evan Phoenix Status: Assigned Priority: Normal Assignee: Nobuyoshi Nakada Category: Target version: ruby -v: - There appears a bug in the handling of concurrent requires of the same file. If a thread (t2) is waiting for another thread (t1) to finish requiring the file, but requiring the file raises an exception, t1 signals t2 and t2 tries to require the file itself. But due to how the loading table is managed, if t1 attempts to require the file again right away (or if another thread were to), it doesn't see an entry in the loading table even though t2 is currently loading the file. This causes t1 to begin requiring the file again or sometimes it raises a ThreadError instead. Here is the code I write for rubyspec to show the bug: start = false fin = false $scratch = [] $con1_ready = false $con1_raise = true path = "path/to/content/below.rb" t1_res = nil t2_res = nil t1 = Thread.new do lambda { require(path) }.should raise_error(RuntimeError) # This hits the bug. Because MRI removes it's internal lock from a table # when the exception is raised, this #require doesn't see that t2 is # in the middle of requiring the file, so this #require runs when it should # not. # # Sometimes this raises a ThreadError also, but I'm not sure why. t1_res = require(path) Thread.pass until fin $scratch << :t1_post end t2 = Thread.new do Thread.pass until $con1_ready begin t2_res = require(path) $scratch << :t2_post ensure fin = true end end t1.join t2.join raise "bug" unless t1_res == false raise "bug" unless t2_res == true $scratch == [:con_pre, :con_pre, :con_post, :t2_post, :t1_post] Here is the file being required: $scratch << :con_pre $con1_ready = true sleep 0.5 if $con1_raise $con1_raise = false raise "con1" end sleep 0.5 $scratch << :con_post -- http://redmine.ruby-lang.org