Project

General

Profile

Actions

Bug #11335

closed

`ruby -r debug` catchpoint problem

Added by sigsys (Math Ieu) about 6 years ago. Updated 6 months ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.1.6p336 (2015-04-13 revision 50298) [i386-freebsd10]
[ruby-core:69878]
Tags:

Description

With a test-debug.rb like this:

raise 'test'

And starting the debugger like this:

ruby -r debug test-debug.rb

By default, the catchpoint is StandardError, but it doesn't work:

test-debug.rb:1:raise 'test'
(rdb:1) catch
Catchpoint StandardError.
(rdb:1) c
test-debug.rb:1:in `<main>': test (RuntimeError)

And the debugger exits without catching the exception.

But, by setting the catchpoint to NilClass (or one of its ancestors), then it works:

test-debug.rb:1:raise "test"
(rdb:1) catch NilClass
Set catchpoint NilClass.
(rdb:1) c
test-debug.rb:1: `' (NilClass)
        from test-debug.rb:1:in `<main>'
test-debug.rb:1:raise "test"

And the debugger does not exit and allows further debugging.

By looking at lib/debug.rb, it looks like that the set_trace_func callback it sets assumes that $! will be set to the exception to be raised when a 'raise' event occurs. But it is not the case, $! seems to always be nil.

Updated by oleynikov (Alexander Oleynikov) almost 3 years ago

I was able to reproduce the issue on newer Ruby.

$ ruby -v
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-openbsd]

sigsys (Math Ieu) wrote:

By looking at lib/debug.rb, it looks like that the set_trace_func callback it sets assumes that $! will be set to the exception to be raised when a 'raise' event occurs. But it is not the case, $! seems to always be nil.

Exactly. When set_trace_func handler proc gets executed with a 'raise' event, the $! is still nil.
DEBUGGER__::Context#excn_handle wants to find a class of the raised exception in $!, but always finds nil there.

We could fix that by replacing Kernel#set_trace_func with TracePoint. It is the recommended way according to the docs, where set_trace_func since Ruby 2.1 contains a note, saying "this method is obsolete, please use TracePoint instead". Instead of $! we should use TracePoint#raised_exception to get correct results.

I'm a bit afraid to work on this issue myself, because I found no specs for the debugger and I can accidentally break something without noticing. But if nobody else is interested in doing this, I will try.

Updated by jeremyevans0 (Jeremy Evans) 7 months ago

I was able to reproduce this issue and confirm that the catch support is broken and has been broken since Ruby 2.0, since the raise event for set_trace_func is not triggered until after $! has been reset:

$ cat t/t13.rb
  set_trace_func proc { |*args|
    p $! if args.first == "raise"
  }

raise 'foo'

$ ruby19 -v t/t13.rb
ruby 1.9.3p551 (2014-11-13 revision 48407) [x86_64-openbsd]
#<RuntimeError: foo>
t/t13.rb:5:in `<main>': foo (RuntimeError)

$ ruby20 -v t/t13.rb
ruby 2.0.0p648 (2015-12-16 revision 53162) [x86_64-openbsd]
nil
t/t13.rb:5:in `<main>': foo (RuntimeError)

Rewriting debug using tracepoint is one option, but I suspect most people would use an alternative debugger such as byebug, so I'm not sure it is worth the effort to switch. Maybe it is just time to retire debug?

Updated by ko1 (Koichi Sasada) 6 months ago

  • Status changed from Open to Closed

I'm rewriting lib/debug.rb with TracePoint.
And I close this ticket because it is too old.
Ruby 3.1 will have better debugger by default :)

Actions

Also available in: Atom PDF