Skip to content

Commit ccc6ae7

Browse files
committed
Clear and restore errinfo on entry to and normal return from C.
1 parent 13ba0da commit ccc6ae7

File tree

4 files changed

+31
-1
lines changed

4 files changed

+31
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Bug fixes:
1010
* Show the interleaved host and guest stacktrace for host exceptions (#2226).
1111
* Fix the label of the first location reported by `Thread#backtrace_locations` (#2229).
1212
* Fix `Thread.handle_interrupt` to defer non-pure interrupts until the end of the `handle_interrupt` block (#2219).
13+
* Clear and restore errinfo on entry and normal return from methods in C extensions (#2227).
1314

1415
Compatibility:
1516

lib/truffle/truffle/cext_ruby.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,16 @@ def rb_define_method(mod, name, function, argc)
3131
args = [Primitive.cext_wrap(self), *args.map! { |arg| Primitive.cext_wrap(arg) }]
3232
end
3333

34+
exc = $!
35+
Truffle::Type.set_last_exception(nil)
3436
# Using raw execute instead of #call here to avoid argument conversion
3537

3638
# We must set block argument if given here so that the
3739
# `rb_block_*` functions will be able to find it by walking the
3840
# stack.
39-
Primitive.cext_unwrap(Primitive.call_with_c_mutex_and_frame(function, args, block))
41+
res = Primitive.cext_unwrap(Primitive.call_with_c_mutex_and_frame(function, args, block))
42+
Truffle::Type.set_last_exception(exc)
43+
res
4044
end
4145

4246
mod.define_method(name, method_body)

spec/ruby/optional/capi/exception_spec.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,26 @@
3838
end
3939
end
4040

41+
describe "rb_errinfo" do
42+
it "is cleared when entering a C method" do
43+
begin
44+
raise StandardError
45+
rescue
46+
$!.class.should == StandardError
47+
@s.rb_errinfo().should == nil
48+
end
49+
end
50+
51+
it "does not clear $! in the calling method" do
52+
begin
53+
raise StandardError
54+
rescue
55+
@s.rb_errinfo()
56+
$!.class.should == StandardError
57+
end
58+
end
59+
end
60+
4161
describe "rb_set_errinfo" do
4262
after :each do
4363
@s.rb_set_errinfo(nil)

spec/ruby/optional/capi/ext/exception_spec.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
extern "C" {
99
#endif
1010

11+
VALUE exception_spec_rb_errinfo(VALUE self) {
12+
return rb_errinfo();
13+
}
14+
1115
VALUE exception_spec_rb_exc_new(VALUE self, VALUE str) {
1216
char *cstr = StringValuePtr(str);
1317
return rb_exc_new(rb_eException, cstr, strlen(cstr));
@@ -41,6 +45,7 @@ VALUE exception_spec_rb_make_exception(VALUE self, VALUE ary) {
4145

4246
void Init_exception_spec(void) {
4347
VALUE cls = rb_define_class("CApiExceptionSpecs", rb_cObject);
48+
rb_define_method(cls, "rb_errinfo", exception_spec_rb_errinfo, 0);
4449
rb_define_method(cls, "rb_exc_new", exception_spec_rb_exc_new, 1);
4550
rb_define_method(cls, "rb_exc_new2", exception_spec_rb_exc_new2, 1);
4651
rb_define_method(cls, "rb_exc_new3", exception_spec_rb_exc_new3, 1);

0 commit comments

Comments
 (0)