Thanks for the information. Sorry for the confusion I caused by describing
the wrong behavior and giving a program that promoted that confusion.

Yes, JRuby does what is most  helpful and what I would expect it to do:
raise an error and continue tracing events. Ruby 1.9's behavior looks to me
like a bug, because after raising the error it gets itself in a state that
prevents further tracing from occurring (except by extraordinary measures
like reinstalling the trace hook).

I think I know how to fix this in Ruby 1.9, and I will post a bug report and
patch to redmine.

Ruby Specification folks: is there any behavior specified right for what
happens when a trace hook raises an error?

Are trace hooks considered part of Ruby or not?

On Thu, Mar 18, 2010 at 2:37 PM, Charles Oliver Nutter
<headius / headius.com>wrote:

> On Thu, Mar 18, 2010 at 5:52 AM, Rocky Bernstein <rockyb / rubyforge.org>
> wrote:
> > The "sort of" part is  that in Ruby 1.9 the implementation of tracing
> sets a
> > bit in the thread structure which turns off tracing into the tracer (or
> > debugging into the debugger). When an exception that passes from hook to
> > non-hook occurs, this bit doesn't get cleared.
>
> That doesn't appear to be the case in JRuby. The bit clearing happens
> in a Java "finally" block, which runs no matter what happens in the
> hook itself. See below.
>
> > Changing the program that was originally posted will show this better:
> >
> > s = Proc.new {
> >   |event, file, lineno, mid, binding, klass|
> >   puts "#{event} #{mid} #{lineno}"
> >   unless $x
> >     $x = true
> >     raise RuntimeError
> >   end
> > }
> > begin
> >   set_trace_func(s)
> >   puts "after trace func"
> > rescue
> >   puts "Rescued"
> > end
> > puts "After begin"
> >
> > Run this in Ruby 1.9 and perhaps it is more apparent that the program
> > continues to the end. In the original posting if you look carefully
> you'll
> > see that the rescue did run *after* the trace hook issued a raise inside
> the
> > begin block. It is the *second* raise issued in the hook function that
> > terminates the program because the debugged program is no longer in a
> > rescue'd block.
>
> In the JRuby case, for your original script, it seemed to take several
> raises for it to terminate. All the trace events appeared to be in the
> main body of code, and not inside the trace hook.
>
> Here's the behavior for the new script in JRuby, which seems to
> continue tracing appropriately after the initial raise inside the hook
>
> ~/projects/jruby  jruby --debug hook_thing2.rb
> line  11 (first event, causes raise)
> c-call === 11 (rescue calling ===)
> c-return === 11 (=== returning)
> line  13 (inside rescue block)
> c-call puts 13 (calling puts)
> c-call write 13 (puts calls write)
> Rescuedc-return write 13 (write returns)
> c-call write 13 (puts calls write again for \n)
>
> c-return write 13 (write returns)
> c-return puts 13 (puts returns)
> line  15 (outside rescue block)
> c-call puts 15 (calling puts)
> c-call write 15 (puts calls write)
> After beginc-return write 15 (write returns)
> c-call write 15 (puts calls write for \n)
>
> c-return write 15 (write returns)
> c-return puts 15 (puts returns)
>
> Is this the output you expected? If not, what do you expect?
>
> > From what you describe from JRuby, it sounds like it has a similar
> behavior
> > possibly because it is implemented underneath in a similar way. So
> > rationalizing this as "this makes sense because this happened in between
> > statements and not in the program" I don't think is accurately capturing
> > what's going inside either interpreter.
>
> Your original script could never do anything but terminate because the
> hooks just kept re-throwing...or at least they did in JRuby, which
> turns tracing back on when the hook is exited, even if it's exited
> abnormally (because of an exception).
>
> - Charlie
>
>