Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.Sign up
Autoload broken by path canonicalization #2788
We have broken autoload in recent weeks or months. I have tracked the problem down to autoload logic not handling RubyGems canonicalization of file paths and our LoadService's failure to recognize that the canonicalized path and the absolute path refer to the same file.
An example of how this breaks:
module Foo autoload :Bar, 'autoloaded.rb' end require_relative 'autoloaded.rb'
module Foo class Bar undef_method :== end end
The resulting stack trace:
It looks like something's awry with undef_method, but what's actually happening is that the autoloaded.rb script is executing twice: once when required directly and once when the first access of Foo::Bar in autoloaded.rb (to open or reopen the Bar class) triggers the autoload.
Our autoload logic detects an in-progress autoload by looking for a circular require. Circular requires are detected by looking in a map of require locks to see if the current thread has already locked this file.
However, if the file is required via an absolute path, the entry in the table does not match and it proceeds to attempt to load the relative path. That execution of undef_method happens first and succeeds, it exits the script body, and then the first load of the autoloaded script proceeds to undef_method a method that isn't there anymore.
Very sneaky, because the error happens without any evidence of the second load in the stack...but I saw this in the context of a rails app with numerous other double-load entries in the backtrace.
This also breaks circular require detection in general, but the autoload scenario is more of an issue because it is so heavily used by Ruby frameworks.
Must be fixed for pre2. This may require another overhaul of LoadService and its management of required and found paths.