Bug #1573

$0 behaves unexpectedly

Added by M B about 6 years ago. Updated over 4 years ago.

[ruby-core:23717]
Status:Closed
Priority:Normal
Assignee:Nobuyoshi Nakada
ruby -v:ruby 1.9.1p0 (2009-01-30 revision 21907) [i386-mswin32] Backport:

Description

=begin
consider two files, foo.rb and bar.rb, both simply contain: "p $0". i run "ruby -rbar.rb foo.rb".

using 1.8.6 and the same setup, the output is:

"foo.rb"
"foo.rb"

using 1.9.1p0 the output is:

"ruby"
"foo.rb"

as a developer, i would expect the old (1.8.6) behavior. i've had arguments that the new behavior is more "correct", as there is no actual script running when the requiring of bar.rb takes place. however, from this correctness, there arises no advantage whatsoever. i am strongly in favor of the old behavior.
=end

History

#1 Updated by Eero Saynatkari about 6 years ago

=begin
Excerpts from Luiz Angelo Daros de Luca's message of Fri Jun 05 19:07:18 +0300 2009:

Bug #1573: $0 behaves unexpectedly
http://redmine.ruby-lang.org/issues/show/1573

Author: Morris Brodersen
Status: Open, Priority: Normal
Category: core
ruby -v: ruby 1.9.1p0 (2009-01-30 revision 21907) [i386-mswin32]

consider two files, foo.rb and bar.rb, both simply contain: "p $0". i run "ruby
-rbar.rb foo.rb".

using 1.8.6 and the same setup, the output is:

"foo.rb"
"foo.rb"

using 1.9.1p0 the output is:

"ruby"
"foo.rb"

as a developer, i would expect the old (1.8.6) behavior. i've had arguments
that the new behavior is more "correct", as there is no actual script running
when the requiring of bar.rb takes place. however, from this correctness, there
arises no advantage whatsoever. i am strongly in favor of the old behavior.

I would argue that the 1.9 (and 1.8.7) version is a better
representation of the actual state of the program.

Further, though, I cannot see a valid use case where the
script being required with -r should know the name of
the assumed eventual script: to me, it implies a problem
with the design and/or the separation of responsibilities.

As always, there may be some use case I am missing?

The "$0 == FILE" trick obviously works the same in both
implementations.

Regards,
Eero
--
Magic is insufficiently advanced technology.

=end

#2 Updated by M B about 6 years ago

=begin

As always, there may be some use case I am missing?

my own use case is a bit hacky and has only syntax advantages:
i'm trying to intercept certain command line arguments, for example
in "ruby foo.rb -test" i would intercept the "-test" and
exec "ruby ./.tests/t_foo.rb" (which is a test suite for foo.rb
previously generated). this is all done in the script "pre.rb"
which i require by the rubyopt environment var (-rpre.rb). it would
need $0 to easily get name of the executed script; there are even
hackier ways of course. i admit that this use case is probably not
very meaningful nor a good design idea. i'd personally like it,
though.

anyway, let us suppose there is no valid use case. you wrote:

Further, though, I cannot see a valid use case where the
script being required with -r should know the name of
the assumed eventual script: to me, it implies a problem
with the design and/or the separation of responsibilities.

we can take this a step further to find ourselves posing
the following questions:

  1. is there any difference between -r'd and require()'d scripts
    regarding the script that is actually run? no!

  2. we can then ask: is their a valid use case for
    require()'d scripts to know $0?

  3. if not, is their any valid use case except the
    $0 == FILE trick?

  4. yet further, what is the point of having $0 if we only
    need it for the trick mentioned above?

the main thing that buggers me though is that $0 == "ruby"
comes totally unexpected. i would never expect it to hold
"ruby" (except when the file itself is named ruby), and i
don't think the average developer would.

i hope my points were clear enough.

regards, morris

update:
additionally, why is ARGV fully available in the -r'd scripts?
we'd have to artificially "hide" ARGV and $0 by your arguments.
that does not make much sense to me.
=end

#3 Updated by Yusuke Endoh over 5 years ago

  • Assignee set to Nobuyoshi Nakada

=begin
Hi,

consider two files, foo.rb and bar.rb, both simply contain: "p $0". i run "ruby -rbar.rb foo.rb".

using 1.8.6 and the same setup, the output is:

"foo.rb"
"foo.rb"

using 1.9.1p0 the output is:

"ruby"
"foo.rb"

I think this is not an intended change.

In fact, nobu fixed this at r23812 (accidentally?) once.
But the symptom reoccers at r25330 for fixing another bug.

Nobu, how about the following patch?

diff --git a/ruby.c b/ruby.c
index 5c1eef0..489942d 100644
--- a/ruby.c
+++ b/ruby.c
@@ -1353,6 +1353,8 @@ process_options(int argc, char **argv, struct cmdline_options *opt)
}
}
ruby_init_gems(!(opt->disable & DISABLE_BIT(gems)));
+ rb_progname = opt->script_name;
+ rb_vm_set_progname(rb_progname);
ruby_set_argv(argc, argv);
process_sflag(&opt->sflag);

@@ -1397,8 +1399,6 @@ process_options(int argc, char **argv, struct cmdline_options *opt)
tree = load_file(parser, opt->script, 1, opt);
});
}
- rb_progname = opt->script_name;
- rb_vm_set_progname(rb_progname);
if (opt->dump & DUMP_BIT(yydebug)) return Qtrue;

  if (opt->ext.enc.index >= 0) {

@@ -1590,7 +1590,12 @@ load_file_internal(VALUE arg)
else if (!NIL_P(c)) {
rb_io_ungetbyte(f, c);
}
- require_libraries(&opt->req_list); /* Why here? unnatural /
+ {
+ VALUE progname = rb_progname;
+ rb_progname = Qnil;
+ require_libraries(&opt->req_list); /
Why here? unnatural */
+ rb_progname = progname;
+ }
}
if (opt->src.enc.index >= 0) {
enc = rb_enc_from_index(opt->src.enc.index);

--
Yusuke Endoh mame@tsg.ne.jp
=end

#4 Updated by Yukihiro Matsumoto over 5 years ago

=begin
Hi,

In message "Re: [Bug #1573] $0 behaves unexpectedly"
on Sat, 10 Apr 2010 11:34:01 +0900, Yusuke Endoh redmine@ruby-lang.org writes:

|Nobu, how about the following patch?

I am not him, but you go ahead.

                        matz.

=end

#5 Updated by Yusuke Endoh about 5 years ago

  • Priority changed from Normal to 3
  • Target version set to 2.0.0

=begin
Hi,

I am not him, but you go ahead.

Sorry, my patch does not work, though I cannot remember what I thought
when writing the patch...

$ ./ruby -I. -rbar foo.rb
nil
"foo.rb"

This issue is caused on r25330.
The purpose of r25330 is to hide script name in load error of -r option:

before r25330:

$ ./ruby -rnotexist -ep
-e:0:in `require': cannot load such file -- notexist (LoadError)

after r25330:

$ ./ruby -rnotexist -ep
./ruby:0:in `require': cannot load such file -- notexist (LoadError)

But I prefer "-e:0". I suggest reverting r25330.

Anyway, it is too late to fix 1.9.2.
This would be fixed after 1.9.3 or later.

--
Yusuke Endoh mame@tsg.ne.jp
=end

#6 Updated by Nobuyoshi Nakada about 5 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

=begin
This issue was solved with changeset r28161.
Morris, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

=end

Also available in: Atom PDF