Bug #20455
openrb_errinfo() inconsistent with $! in the caller Ruby code
Description
This (slightly modified for clarity) test in ruby/spec demonstrates the unexpected result:
describe "rb_errinfo" do
def err
$!
end
it "is cleared when entering a C method" do
begin
raise StandardError
rescue
$!.class.should == StandardError
err.class.should == StandardError
@s.rb_errinfo().should == nil
end
end
Why does rb_errinfo()
return nil there, when $! is set in the caller (and $! isn't per frame but per thread, as shown with err
)?
Is this bug?
If not, what is the logic and reason for clearing $!
when calling a method defined in C?
Updated by Eregon (Benoit Daloze) 6 months ago
@ko1 (Koichi Sasada) (and the code) pointed me to $!
is rb_ec_get_errinfo
, which walks the stack to find the first rescue
/ensure
(does it stop at the first ensure if it's an ensure without an active exception?) and uses ec->errinfo
if not,
while rb_errinfo
is just GET_EC()->errinfo
.
I'm not sure what this means in terms of semantics, that they are the same but only if no rescue/ensure on the stack, and otherwise they are fully separate?
It sounds like very odd semantics.
BTW the header docs at https://github.com/ruby/ruby/blob/6f4f360fc46269eaba753cafe557519677a45a11/include/ruby/internal/error.h#L77-L84 seems not quite true and rather misleading.