-
Notifications
You must be signed in to change notification settings - Fork 185
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Truffleruby loses $! after rb_exc_raise
#2890
Comments
rb_exc_raise
rb_exc_raise
Thank you for the report. I'll debug it further, I thought it's simply |
This seems caused by this change: 19f0e6a So it seems the semantics |
I tried looking in CRuby if/how they clear There is some handling of I found quite a few place doing The strange behavior is the behavior of this spec which passes on CRuby: def err
$!
end
it "is cleared when entering a C method" do
$!.should == nil
begin
raise StandardError
rescue
$!.class.should == StandardError
err.class.should == StandardError
@s.rb_errinfo().should == nil
end
end I don't understand why rb_errinfo() is nil there and what sets it to OTOH rb_raise()->rb_longjmp()->exc_setup_message()->errinfo_place() has some complex logic where it gets the errinfo from a Ruby frame on the stack instead of just reading |
@aardvark179 Would you remember where/how CRuby sets |
I'm looking at this a bit again, @nirvdrum reported a similar issue. require "openssl"
begin
p in_first_begin: $!
raise StandardError, "aaa"
rescue Exception
p in_first_rescue: $!
begin
# this works since it generates an ArgumentError before calling into C-ext:
# OpenSSL::Random.random_bytes
# but this loses the exception context, since it raises ArgumentError from a C-ext:
OpenSSL::Random.random_bytes(-1)
p in_second_begin: $!
rescue ArgumentError
p in_second_rescue: $!
end
p after_second_begin_rescue_end: $!
# should raise StandardError "aaa" but raises RuntimeError ""
raise
# this works and raises the StandardError "aaa"
# raise err
end We get:
So
If we just revert 19f0e6a changes in cext_ruby.rb we fail that spec though (OTOH, the rest of :cext specs passes, and jt test mri --cext too, but I think @aardvark179 did this change to fix pg or some other C ext so we should check that).
|
I filed a CRuby issue for this because it's not clear to me if clearing $! on calling a method defined in C is intended or a CRuby bug: https://bugs.ruby-lang.org/issues/20455 |
After thinking about this more and what I understood from the CRuby semantics and discussion with Koichi, I think the best fix for now is to use a completely separate storage for BTW, currently we have
But
So |
I managed to reproduce a similar error, but using yaml: require 'yaml'
def function
raise StandardError, "custom message"
rescue StandardError
puts $!.message
data = "yaml: str"
valid_result = YAML.unsafe_load(data)
puts "Valid yaml" if valid_result == {"yaml" => "str"}
raise
end
begin
function
rescue Exception => e
puts "#{e.class}: '#{e.message}'"
puts e.backtrace
end ruby -v
truffleruby 24.0.1, like ruby 3.2.2, Oracle GraalVM Native [aarch64-darwin] |
* Make $! Fiber-local. * Rename Primitive.thread_get_exception to Primitive.fiber_get_exception for clarity. * Fixes oracle/truffleruby#2890
While developing ruby-pg I noticed a bug in Truffleruby. I replaced the pg gem by openssl, to use a stdlib:
It looks to me like a call to
rb_exc_raise
or sibling in a C-extension clear the exception context, so that the second raise in the sample above acts like an ordinary raise outside of the rescue branch.Context:
The text was updated successfully, but these errors were encountered: