mirror of
https://github.com/ruby/ruby.git
synced 2026-01-26 12:14:51 +00:00
Let Ractor::IsolationError report correct constant path
Before this patch, Ractor::IsolationError reported an incorrect constant
path when constant was found through `rb_const_get_0()`.
In this code, Ractor::IsolationError reported illegal access against
`M::TOPLEVEL`, where it should be `Object::TOPLEVEL`.
```ruby
TOPLEVEL = [1]
module M
def self.f
TOPLEVEL
end
end
Ractor.new { M.f }.value
```
This was because `rb_const_get_0()` built the "path" part referring to
the module/class passed to it in the first place. When a constant was
found through recursive search upwards, the module/class which the
constant was found should be reported.
This patch fixes this issue by modifying rb_const_search() to take a
VALUE pointer to be filled with the module/class where the constant was
found.
[Bug #21782]
This commit is contained in:
parent
2d01406644
commit
cbcbbb2fbe
Notes:
git
2025-12-17 01:16:28 +00:00
@ -1089,6 +1089,20 @@ assert_equal "can not access non-shareable objects in constant Object::STR by no
|
||||
end
|
||||
RUBY
|
||||
|
||||
# The correct constant path shall be reported
|
||||
assert_equal "can not access non-shareable objects in constant Object::STR by non-main Ractor.", <<~'RUBY', frozen_string_literal: false
|
||||
STR = "hello"
|
||||
module M
|
||||
def self.str; STR; end
|
||||
end
|
||||
|
||||
begin
|
||||
Ractor.new{ M.str }.join
|
||||
rescue Ractor::RemoteError => e
|
||||
e.cause.message
|
||||
end
|
||||
RUBY
|
||||
|
||||
# Setting non-shareable objects into constants by other Ractors is not allowed
|
||||
assert_equal 'can not set constants with non-shareable objects by non-main Ractors', <<~'RUBY', frozen_string_literal: false
|
||||
class C
|
||||
|
||||
23
variable.c
23
variable.c
@ -63,7 +63,7 @@ static VALUE autoload_mutex;
|
||||
|
||||
static void check_before_mod_set(VALUE, ID, VALUE, const char *);
|
||||
static void setup_const_entry(rb_const_entry_t *, VALUE, VALUE, rb_const_flag_t);
|
||||
static VALUE rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility);
|
||||
static VALUE rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility, VALUE *found_in);
|
||||
static st_table *generic_fields_tbl_;
|
||||
|
||||
typedef int rb_ivar_foreach_callback_func(ID key, VALUE val, st_data_t arg);
|
||||
@ -473,7 +473,7 @@ rb_path_to_class(VALUE pathname)
|
||||
if (!id) {
|
||||
goto undefined_class;
|
||||
}
|
||||
c = rb_const_search(c, id, TRUE, FALSE, FALSE);
|
||||
c = rb_const_search(c, id, TRUE, FALSE, FALSE, NULL);
|
||||
if (UNDEF_P(c)) goto undefined_class;
|
||||
if (!rb_namespace_p(c)) {
|
||||
rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module",
|
||||
@ -3352,11 +3352,12 @@ rb_const_warn_if_deprecated(const rb_const_entry_t *ce, VALUE klass, ID id)
|
||||
static VALUE
|
||||
rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
|
||||
{
|
||||
VALUE c = rb_const_search(klass, id, exclude, recurse, visibility);
|
||||
VALUE found_in;
|
||||
VALUE c = rb_const_search(klass, id, exclude, recurse, visibility, &found_in);
|
||||
if (!UNDEF_P(c)) {
|
||||
if (UNLIKELY(!rb_ractor_main_p())) {
|
||||
if (!rb_ractor_shareable_p(c)) {
|
||||
rb_raise(rb_eRactorIsolationError, "can not access non-shareable objects in constant %"PRIsVALUE"::%s by non-main Ractor.", rb_class_path(klass), rb_id2name(id));
|
||||
rb_raise(rb_eRactorIsolationError, "can not access non-shareable objects in constant %"PRIsVALUE"::%s by non-main Ractor.", rb_class_path(found_in), rb_id2name(id));
|
||||
}
|
||||
}
|
||||
return c;
|
||||
@ -3365,7 +3366,7 @@ rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_const_search_from(VALUE klass, ID id, int exclude, int recurse, int visibility)
|
||||
rb_const_search_from(VALUE klass, ID id, int exclude, int recurse, int visibility, VALUE *found_in)
|
||||
{
|
||||
VALUE value, current;
|
||||
bool first_iteration = true;
|
||||
@ -3402,13 +3403,17 @@ rb_const_search_from(VALUE klass, ID id, int exclude, int recurse, int visibilit
|
||||
if (am == tmp) break;
|
||||
am = tmp;
|
||||
ac = autoloading_const_entry(tmp, id);
|
||||
if (ac) return ac->value;
|
||||
if (ac) {
|
||||
if (found_in) { *found_in = tmp; }
|
||||
return ac->value;
|
||||
}
|
||||
rb_autoload_load(tmp, id);
|
||||
continue;
|
||||
}
|
||||
if (exclude && tmp == rb_cObject) {
|
||||
goto not_found;
|
||||
}
|
||||
if (found_in) { *found_in = tmp; }
|
||||
return value;
|
||||
}
|
||||
if (!recurse) break;
|
||||
@ -3420,17 +3425,17 @@ rb_const_search_from(VALUE klass, ID id, int exclude, int recurse, int visibilit
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility)
|
||||
rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility, VALUE *found_in)
|
||||
{
|
||||
VALUE value;
|
||||
|
||||
if (klass == rb_cObject) exclude = FALSE;
|
||||
value = rb_const_search_from(klass, id, exclude, recurse, visibility);
|
||||
value = rb_const_search_from(klass, id, exclude, recurse, visibility, found_in);
|
||||
if (!UNDEF_P(value)) return value;
|
||||
if (exclude) return value;
|
||||
if (BUILTIN_TYPE(klass) != T_MODULE) return value;
|
||||
/* search global const too, if klass is a module */
|
||||
return rb_const_search_from(rb_cObject, id, FALSE, recurse, visibility);
|
||||
return rb_const_search_from(rb_cObject, id, FALSE, recurse, visibility, found_in);
|
||||
}
|
||||
|
||||
VALUE
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user