Skip to content

Commit 9633bbe

Browse files
committed
Include ivar name and class name in the Ractor isolation error message
- ### Problem When a Ractor isolation error happens due to setting an ivar on a class, the message doesn't include the name of the ivar and neither the name of the class. It makes it difficult to track down where the isolation problem comes from. I'd like the message to be similar as what we get when a Ractor access an unshareable ivar. This is the current behaviour ```ruby class Foo def self.foo @foo ||= "test" end end Ractor.new do Foo.foo # can not set instance variables of classes/modules by non-main Ractors end.join Foo.foo Ractor.new do Foo.foo # can not get unshareable values from instance variables of classes/modules from non-main Ractors (@foo from Foo) end.join ``` ### Solution Modify the error message to include the ivar name and the class/module name.
1 parent 1790ac4 commit 9633bbe

2 files changed

Lines changed: 29 additions & 5 deletions

File tree

bootstraptest/test_ractor.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,25 @@ class C
864864
end
865865
RUBY
866866

867+
# setting an ivar of a class/module from a non-main Ractor reports the ivar and class
868+
assert_equal "can not set instance variables of classes/modules by non-main Ractors (@iv from C)", <<~'RUBY', frozen_string_literal: false
869+
class C
870+
@iv = 'str'
871+
end
872+
873+
r = Ractor.new do
874+
class C
875+
@iv = 'other'
876+
end
877+
end
878+
879+
begin
880+
r.value
881+
rescue Ractor::RemoteError => e
882+
e.cause.message
883+
end
884+
RUBY
885+
867886
# ivar in shareable-objects are not allowed to access from non-main Ractor
868887
assert_equal 'can not access instance variables of shareable objects from non-main Ractors', %q{
869888
shared = Ractor.new{}

variable.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,11 +1199,16 @@ rb_alias_variable(ID name1, ID name2)
11991199
}
12001200

12011201
static void
1202-
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(ID id)
1202+
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(VALUE obj, ID id)
12031203
{
12041204
if (UNLIKELY(!rb_ractor_main_p())) {
12051205
if (rb_is_instance_id(id)) { // check only normal ivars
1206-
rb_raise(rb_eRactorIsolationError, "can not set instance variables of classes/modules by non-main Ractors");
1206+
rb_raise(
1207+
rb_eRactorIsolationError,
1208+
"can not set instance variables of classes/modules by non-main Ractors (%"PRIsVALUE" from %"PRIsVALUE")",
1209+
rb_id2str(id),
1210+
obj
1211+
);
12071212
}
12081213
}
12091214
}
@@ -1595,7 +1600,7 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef)
15951600
int type = BUILTIN_TYPE(obj);
15961601

15971602
if (type == T_CLASS || type == T_MODULE) {
1598-
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
1603+
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(obj, id);
15991604

16001605
if (rb_multi_ractor_p()) {
16011606
concurrent = true;
@@ -1968,7 +1973,7 @@ ivar_set(VALUE obj, ID id, VALUE val)
19681973
case T_CLASS:
19691974
case T_MODULE:
19701975
{
1971-
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
1976+
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(obj, id);
19721977
bool dontcare;
19731978
return class_ivar_set(obj, id, val, &dontcare);
19741979
}
@@ -2262,7 +2267,7 @@ rb_field_foreach(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg,
22622267
case T_CLASS:
22632268
case T_MODULE:
22642269
{
2265-
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(0);
2270+
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(obj, 0);
22662271
VALUE fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
22672272
if (fields_obj) {
22682273
imemo_fields_each(fields_obj, func, arg, ivar_only);

0 commit comments

Comments
 (0)