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) over 1 year 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.