SystemStackError is silenced
In this code:
require 'interception'
Interception.listen do |a, b|
puts a, b
end
def foo
foo
end
foo
puts 'done'
It silences the error and totally eats any debug messages:
$ ruby /tmp/a.rb
$ echo $?
1
We expected to get something similar to what you get without your gem:
$ cat /tmp/a.rb
def foo
foo
end
foo
puts 'done'
$ ruby /tmp/a.rb
/tmp/a.rb:2:in `foo': stack level too deep (SystemStackError)
from /tmp/a.rb:2:in `foo'
from /tmp/a.rb:2:in `foo'
from /tmp/a.rb:2:in `foo'
from /tmp/a.rb:2:in `foo'
from /tmp/a.rb:2:in `foo'
from /tmp/a.rb:2:in `foo'
from /tmp/a.rb:2:in `foo'
from /tmp/a.rb:2:in `foo'
... 10067 levels...
from /tmp/a.rb:2:in `foo'
from /tmp/a.rb:2:in `foo'
from /tmp/a.rb:2:in `foo'
from /tmp/a.rb:5:in `<main>'
At a guess, during a SystemStackError we have extremely few stack frames to work with (since the stack is yet to be unwound), and something (my guess is https://github.com/ConradIrwin/interception/blob/master/lib/interception.rb#L104-L106) in interception is causing us to blow the stack again, re-entering our raise TracePoint.
Since that call occurs in a self.rescueing = true block, all further exceptions are nop'd.
Thoughts?
Stack errors are almost always fatal; they can happen inside teardown code, leaving resources dangling. Intercepting stack errors almost never works like you expect.
It looks like the root cause is TracePoint, which Interception relies on; I'm able to reproduce with TracePoint alone:
TracePoint.new(:raise){}.enable
def foo; foo; end
foo
This bug has been filed with Ruby for a year, but so far no response: https://bugs.ruby-lang.org/issues/11667.
Welp.