Bug #11493
closedIRB/Ruby completely exits when attempting to use NoMethodError exception in BasicObject
Description
Summary¶
Was playing around with BasicObject to implement my own undefined method message and found this issue in IRB
$ ruby --version
ruby 2.2.0p0 (2014-12-25 revision 49005) [x86_64-darwin14]
$ irb
2.2.0 :002 > class BasicObject
2.2.0 :003?> def method_missing(name, *args, &block)
2.2.0 :004?> raise(NoMethodError, " '#{name}' is an undefined method, dude!")
2.2.0 :005?> end
2.2.0 :006?> end
=> :method_missing
2.2.0 :008 > 234234.asdasdasd
NameError: uninitialized constant BasicObject::NoMethodError
(irb):4:in `method_missing': uninitialized constant BasicObject::NoMethodError (NameError)
from /Users/home/.rvm/scripts/irbrc.rb:32:in `initialize'
from /Users/home/.rvm/scripts/irbrc.rb:32:in `open'
from /Users/home/.rvm/scripts/irbrc.rb:32:in `block in <top (required)>'
(irb):4:in `method_missing': uninitialized constant BasicObject::NoMethodError (NameError)
from /Users/home/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/irb/workspace.rb:106:in `sub'
from /Users/home/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/irb/workspace.rb:106:in `filter_backtrace'
from /Users/home/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/irb.rb:511:in `block (3 levels) in eval_input'
from /Users/home/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/irb.rb:510:in `each'
from /Users/home/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/irb.rb:510:in `block (2 levels) in eval_input'
from /Users/home/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/irb.rb:623:in `signal_status'
from /Users/home/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/irb.rb:486:in `block in eval_input'
from /Users/home/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/irb/ruby-lex.rb:245:in `block (2 levels) in each_top_level_statement'
from /Users/home/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/irb/ruby-lex.rb:231:in `loop'
from /Users/home/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/irb/ruby-lex.rb:231:in `block in each_top_level_statement'
from /Users/home/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/irb/ruby-lex.rb:230:in `catch'
from /Users/home/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/irb/ruby-lex.rb:230:in `each_top_level_statement'
from /Users/home/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/irb.rb:485:in `eval_input'
from /Users/home/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/irb.rb:395:in `block in start'
from /Users/home/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/irb.rb:394:in `catch'
from /Users/home/.rvm/rubies/ruby-2.2.0/lib/ruby/2.2.0/irb.rb:394:in `start'
from /Users/home/.rvm/rubies/ruby-2.2.0/bin/irb:11:in `<main>'
$ echo $?
1
Expected Results¶
I expect IRB to handle Ruby errors without exiting completely. The same way "foo".asdfasdf() raises a NoMethodError, but doesn't actually completely die.
Actual Results¶
Fatal error resulting in the Ruby process exiting.
Updated by jeremyevans0 (Jeremy Evans) over 5 years ago
This error still occurs in master. However, I'm not sure it is fixable with the example you gave. Your example does not raise NoMethodError
, it raises NameError
, because you used NoMethodError
instead of ::NoMethodError
. Even if you fix that, defining BasicObject#method_missing
overrides the existing version, which breaks ton of internal code, not just irb. Even a simple thing like using backticks is broken if you do that (and irb ends up using backticks), because Ruby will attempt to call such a method_missing
method (in rb_check_funcall_default
) in many cases.
If you do want to wrap NoMethodError
s with a different exception message, you could try:
module BasicObjectMM
def method_missing(name, *args, &block)
super
rescue => e
e.message.replace("'#{name}' is an undefined method, dude!")
::Kernel.raise(e)
end
end
BasicObject.prepend(BasicObjectMM)
Updated by ko1 (Koichi Sasada) over 5 years ago
- Assignee set to aycabta (aycabta .)
Updated by ko1 (Koichi Sasada) over 5 years ago
- Status changed from Open to Rejected
could you make an issue and continue to discuss on https://github.com/ruby/irb ?
Thanks,
Koichi