In Ruby Next, I want to be able to "catch" syntax errors occurred while requiring a file to transpile this file on-the-fly and evaluate (ruby -ruby-next some_ruby_file_with_edge_syntax.rb, see uby-next.rb).
To make this work I use at_exit hook and check whether $! is a SyntaxError, try to re-load the transpiled version and call exit!(0) if that works.
In TruffleRuby, at_exit block is called, we can access the exception via $! but calling exit!(0) has no effect鈥攖he exit status is still >0.
Also, the exception message is printed as well (in MRI, if we "caught" the exception, there is no err output).
Here is the minimal reproduction: https://github.com/palkan/ruby-compatibility-examples/blob/master/examples/at_exit_rescue.rb
And here is the failing CI build with the output: https://github.com/palkan/ruby-compatibility-examples/runs/864905161?check_suite_focus=true
P.S. There you can find how MRI and JRuby handle this. (JRuby sets the correct exit status but still prints the error message).
/cc @ssnickolay
try to re-load the transpiled version and call
exit!(0)if that works.
I don't understand this bit - if you can successfully transpile and reload... you then exit? Why don't you then keep going with the transpiled code?
The exit!(0) is a way to suppress the original SyntaxError, which would otherwise be shown.
But the exit!(0) doesn't actually cause the process to exit? I thought after transpiling you'd want to continue?
There is an eval() and then it exits: https://github.com/ruby-next/ruby-next/blob/d3d075fa60b3da82d1f949ca4ad5ec2ca5b2ae96/lib/uby-next.rb#L66-L67
I've tested locally and didn't see the error (note: the TR build includes not released fix for refine_include_super.rb):

p.s. for JRuby I see described behaviour (print error stack trace but correct exit status)
SyntaxError: /Users/ssnickolay/Projects/oss/ruby-compatibility-examples/support/invalid_syntax.rb:1: syntax error, unexpected '}'
invalid_hash = {x: }
^
require at org/jruby/RubyKernel.java:974
require_relative at org/jruby/RubyKernel.java:1002
<main> at examples/at_exit_rescue.rb:8
We catched it!
@ssnickolay https://github.com/palkan/ruby-compatibility-examples/blob/master/run-all.rb assumes you're running with the ruby to test in PATH.
I can reproduce on master, I'm working on a fix.
assumes you're running with the ruby to test in PATH.
Yeah, I didn't read carefully run-all.rb
Fixed in e9dce4a8d216454de7273fb3780a17c18a811574, thanks for the report and reproducer!
Sorry, but I broke it again 馃檭
Here is a bit more complex example: https://github.com/palkan/ruby-compatibility-examples/commit/f92c69c0366e1c3b656d2ef7aead4a1a79bb5c0b (and the corresponding CI build: https://github.com/palkan/ruby-compatibility-examples/runs/884982846?check_suite_focus=true).
This time, we define at_exit hook in the required file (-r), not the one we execute. That could be the reason.
P.S. I can open a new issue if you'd like.
I'll take a look, thanks for the reproducer :smiley:
Run examples/cli_require_at_exit.rb: 馃挜 truffleruby:
examples/../support/typo.rb:1: syntax error, unexpected tRCURLY (SyntaxError)
examples/cli_require_at_exit.rb:2:in `<main>': Assertion failed: (RuntimeError)
It seems the issue in that case is that the SyntaxError happens in the "main script file" and so before TruffleRuby enters TopLevelRaiseHandler.
That example is fixed with efa38abf2be8e55900f92259c56f90cda8f896bf.