Bug #555

method_missing in Gem module removes some necessary methods

Added by Akira Matsuda over 3 years ago. Updated 10 months ago.

[ruby-core:18527]
Status:Closed Start date:09/10/2008
Priority:Normal Due date:12/24/2008
Assignee:Eric Hodel % Done:

100%

Category:lib
Target version:1.9.1 Release Candidate
ruby -v:

Description

I found something strange in Ruby 1.9 bundled Rubygems(gem_prelude.rb).

(1) there's a method named default_dir in Gem module, which returns a certain directory name
 Gem.default_dir
 #=> "/Users/matsuda/ruby/lib/ruby/gems/1.9.0"

(2) call a missing method on Gem module to make a method_missing call
 Gem.foo
 NoMethodError: undefined method `foo' for Gem:Module
     from gem_prelude.rb:192:in `method_missing'
     from (irb):12
     from /Users/matsuda/ruby/bin/irb19:12:in `<main>'

(3) method_missing undefs Gem::GEM_PRELUDE_METHODS.each methods inside Gem.method_missing -> QuickLoader.load_full_rubygems_library

(4) Gem.default_dir still alives
 Gem.default_dir
 #=> "/Users/matsuda/ruby/lib/ruby/gems/1.9.0"

(5) invoke method_missing again
 Gem.foo
 /Users/matsuda/ruby/lib/ruby/1.9.0/rubygems.rb:82: warning: already initialized constant MUTEX
 /Users/matsuda/ruby/lib/ruby/1.9.0/rubygems.rb:84: warning: already initialized constant RubyGemsPackageVersion
 /Users/matsuda/ruby/lib/ruby/1.9.0/rubygems.rb:89: warning: already initialized constant WIN_PATTERNS
 /Users/matsuda/ruby/lib/ruby/1.9.0/rubygems.rb:742: warning: already initialized constant MARSHAL_SPEC_DIR
 /Users/matsuda/ruby/lib/ruby/1.9.0/rubygems.rb:744: warning: already initialized constant YAML_SPEC_DIR
 NoMethodError: undefined method `foo' for Gem:Module
     from gem_prelude.rb:192:in `method_missing'
     from (irb):14
     from /Users/matsuda/ruby/bin/irb19:12:in `<main>'

(6) Gem.default_dir disappears!
 Gem.default_dir
 NameError: undefined method `default_dir' for `Gem'
     from gem_prelude.rb:78:in `undef_method'
     from gem_prelude.rb:78:in `block in singletonclass'
     from gem_prelude.rb:77:in `each'
     from gem_prelude.rb:77:in `singletonclass'
     from gem_prelude.rb:76:in `load_full_rubygems_library'
     from gem_prelude.rb:191:in `method_missing'
     from (irb):15
     from /Users/matsuda/ruby/bin/irb19:12:in `<main>'

I noticed that some gems don't work well on Ruby 1.9 because of this behavior.

Ruby version: revision 19146
gem -v: 1.2.0.1824

Associated revisions

Revision 20923
Added by Eric Hodel about 3 years ago

Don't remove methods twice. [bug#555]

History

Updated by Koichi Sasada over 3 years ago

  • Assignee set to Eric Hodel

Updated by Yuki Sonoda over 3 years ago

  • Category set to lib
  • Target version set to 1.9.0-5

Updated by Yuki Sonoda about 3 years ago

  • Target version changed from 1.9.0-5 to 1.9.1 Release Candidate

Updated by Yuki Sonoda about 3 years ago

I'll ask Eric whether it still happens

Updated by Eric Hodel about 3 years ago

I think this patch would fix it:

Index: gem_prelude.rb
===================================================================
--- gem_prelude.rb	(revision 20650)
+++ gem_prelude.rb	(working copy)
@@ -172,6 +172,7 @@ if defined?(Gem) then
     # with the real RubyGems

     GEM_PRELUDE_METHODS = Gem.methods(false)
+    GEM_PRELUDE_METHODS << :method_missing

     begin
       verbose, debug = $VERBOSE, $DEBUG

but I get a crash:

(gdb) run -v test.rb
Starting program: /usr/local/bin/ruby19 -v test.rb
Reading symbols for shared libraries +++... done
ruby 1.9.1 (2008-12-12 revision 20648) [i386-darwin9.5.0]
[...]

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x0000012c
0x0010f1dd in vm_exec (th=0x200710) at vm.c:1071
1071		epc = cfp->pc - cfp->iseq->iseq_encoded;
(gdb) bt
#0  0x0010f1dd in vm_exec (th=0x200710) at vm.c:1071
#1  0x0010f914 in rb_iseq_eval (iseqval=4094920) at vm.c:1246
#2  0x0002efa9 in ruby_exec_node (n=0x3e7bc8, file=0x0) at eval.c:205
#3  0x000317ee in ruby_run_node (n=0x3e7bc8) at eval.c:233
#4  0x00001f5f in main (argc=3, argv=0x200540) at main.c:35

Updated by Eric Hodel about 3 years ago

May I commit this patch? It is correct:

Index: gem_prelude.rb
===================================================================
--- gem_prelude.rb	(revision 20650)
+++ gem_prelude.rb	(working copy)
@@ -194,7 +194,13 @@ if defined?(Gem) then

     module QuickLoader

+      @loaded_full_rubygems_library = false
+
       def self.load_full_rubygems_library
+        return if @loaded_full_rubygems_library
+
+        @loaded_full_rubygems_library = true
+
         class << Gem
           Gem::GEM_PRELUDE_METHODS.each do |method_name|
             undef_method method_name

It passes this test:

$ cat test.rb
Gem.foo rescue nil
Gem.foo rescue nil
p Gem.default_dir

$ ruby19 -v test.rb
ruby 1.9.1 (2008-12-12 revision 20648) [i386-darwin9.5.0]
"/usr/local/lib/ruby19/gems/1.9.1"

Updated by Yuki Sonoda about 3 years ago

  • Due date set to 12/24/2008

Updated by Eric Hodel about 3 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100
Applied in changeset r20923.

Also available in: Atom PDF