Bug #555

method_missing in Gem module removes some necessary methods

Added by Akira Matsuda over 6 years ago. Updated about 4 years ago.

[ruby-core:18527]
Status:Closed
Priority:Normal
Assignee:Eric Hodel
ruby -v: Backport:

Description

=begin
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 `'

(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 `'

(6) Gem.default_dir disappears!
Gem.default_dir
NameError: undefined method default_dir' forGem'
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 `'

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
=end

History

#1 Updated by Koichi Sasada over 6 years ago

  • Assignee set to Eric Hodel

=begin

=end

#2 Updated by Yuki Sonoda over 6 years ago

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

=begin

=end

#3 Updated by Yuki Sonoda over 6 years ago

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

=begin

=end

#4 Updated by Yuki Sonoda over 6 years ago

=begin
I'll ask Eric whether it still happens
=end

#5 Updated by Eric Hodel over 6 years ago

=begin
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

=end

#6 Updated by Eric Hodel over 6 years ago

=begin
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"

=end

#7 Updated by Yuki Sonoda over 6 years ago

  • Due date set to 12/24/2008

=begin

=end

#8 Updated by Eric Hodel over 6 years ago

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

=begin
Applied in changeset r20923.
=end

Also available in: Atom PDF