Bug #19726
closed
Script loaded twice when requiring self
Added by johannes (Johannes Krude) about 1 year ago.
Updated about 1 year ago.
ruby -v:
ruby 3.3.0preview1 (2023-05-12 master a1b01e7701) [x86_64-linux]
[ruby-core:113888]
Description
The executed program is not added to $LOADED_FEATURES
unexpectedly resulting in the program possibly being loaded twice:
a.rb:
#!/usr/bin/env ruby
require "./b"
C = 42
return unless __FILE__ == $0
puts C
b.rb:
require "./a"
This results in:
$ ./a.rb
./a.rb:5: warning: already initialized constant C
/home/johannes/t/a.rb:5: warning: previous definition of C was here
42
Ruby version:
$ sudo docker run ruby:3.3.0-preview1 ruby --version
ruby 3.3.0preview1 (2023-05-12 master a1b01e7701) [x86_64-linux]
This could be solved by always adding the executed program to $LOADED_FEATURES
.
As a workaround, executed programs can be prepended with:
require "pathname"
if __FILE__ == $0
$LOADED_FEATURES << Pathname.new(__FILE__).expand_path.to_s
end
- ruby -v set to ruby 3.3.0preview1 (2023-05-12 master a1b01e7701) [x86_64-linux]
Making this change would not be backwards compatible:
# a.rb
if __FILE__ == $0
# $LOADED_FEATURES << File.expand_path(__FILE__) # would break things
require './b'
else
def a
1
end
end
# b.rb
require './a'
p a
The main script is treated specially compared to required files, in ways beyond this. I'm not sure that it is worth changing this and introducing backwards compatibility issues. Especially since this would still be a circular require, which Ruby issues a warning for in verbose warning mode.
A similar case that I have found surprising is if e.g. I use a file for a quick test called like a stdlib, say openssl.rb
, then require 'openssl'
in that file would not require the stdlib but load the main script a second time, if -I.
or so.
That's really unfortunate.
It seems pretty clear nobody wants to load the main script twice, so what's the compatibility issue with adding (the absolute path of the) main script to $LOADED_FEATURES like other (require'd) files?
- Subject changed from Script loadde twice when requiring self to Script loaded twice when requiring self
Proposed change would break irb
at least. Please accept this weird behavior.
Matz.
- Status changed from Open to Rejected
A few additional explanations.
First, the importance of the stated problem is not clear. Circular require should be fixed. The OP should clearly state the background for wanting this resolved (if any).
Also, a critical problem was noted that irb and many CLI tools would stop working with the proposed solution. For example, bin/irb does require "irb"
. With the proposed workaround, $LOADED_FEATRUES
will contain "/path/to/bin/irb"
when the irb command is executed. Then require "irb"
will not read /path/to/lib/irb.rb
, instead return false immediately. Thus, this proposal will make irb and many other CLI tools inoperable.
mame (Yusuke Endoh) wrote in #note-7:
With the proposed workaround, $LOADED_FEATRUES
will contain "/path/to/bin/irb"
when the irb command is executed. Then require "irb"
will not read /path/to/lib/irb.rb
, instead return false immediately. Thus, this proposal will make irb and many other CLI tools inoperable.
Unless I'm missing something, that would be no problem.
Because /path/to/bin
is not in $LOAD_PATH
so it won't be considered for require "irb"
, isn't it?
Also available in: Atom
PDF
Like1
Like0Like0Like0Like0Like0Like0Like0Like0