Skip to content

Commit 20bfb78

Browse files
committed
Singleton classes of unshareable objects are not shareable
Currently, all RClasses are created as shareable in `class_alloc0`, which causes singleton classes of unshareable objects to be shareable which allows passing unshareable objects by passing their singleton class and getting their attached object. This changes `singleton_class_of` to mark the singleton class as shareable when the object is shareable, and inversely, to mark the singleton class as unshareable if the object is unshareable. We also need to not forcibly mark the class as shareable in `shareable_p_enter`. Additionally, if the object is not yet marked as shareable, but is frozen (and `allow_frozen_shareable_p`), it becomes marked as shareable through `rb_ractor_shareable_p`, and we need to also mark its singleton class as shareable at that point.
1 parent 3c63489 commit 20bfb78

3 files changed

Lines changed: 20 additions & 3 deletions

File tree

class.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "internal/string.h"
3030
#include "internal/variable.h"
3131
#include "ruby/st.h"
32+
#include "ruby/ractor.h"
3233
#include "vm_core.h"
3334
#include "ruby/ractor.h"
3435
#include "yjit.h"
@@ -2866,6 +2867,12 @@ singleton_class_of(VALUE obj, bool ensure_eigenclass)
28662867
klass = rb_make_metaclass(obj, klass);
28672868
}
28682869
RB_FL_SET_RAW(klass, RB_OBJ_FROZEN_RAW(obj));
2870+
if (!RB_OBJ_SHAREABLE_P(obj) && RB_OBJ_SHAREABLE_P(klass)) {
2871+
RB_FL_UNSET_RAW(klass, RUBY_FL_SHAREABLE);
2872+
}
2873+
else if (RB_OBJ_SHAREABLE_P(obj) && !RB_OBJ_SHAREABLE_P(klass)) {
2874+
RB_FL_SET_RAW(klass, RUBY_FL_SHAREABLE);
2875+
}
28692876
if (ensure_eigenclass && RB_TYPE_P(obj, T_CLASS)) {
28702877
/* ensures an exposed class belongs to its own eigenclass */
28712878
(void)ENSURE_EIGENCLASS(klass);

depend

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12570,6 +12570,7 @@ ractor.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
1257012570
ractor.$(OBJEXT): $(top_srcdir)/internal/bignum.h
1257112571
ractor.$(OBJEXT): $(top_srcdir)/internal/bits.h
1257212572
ractor.$(OBJEXT): $(top_srcdir)/internal/box.h
12573+
ractor.$(OBJEXT): $(top_srcdir)/internal/class.h
1257312574
ractor.$(OBJEXT): $(top_srcdir)/internal/compilers.h
1257412575
ractor.$(OBJEXT): $(top_srcdir)/internal/complex.h
1257512576
ractor.$(OBJEXT): $(top_srcdir)/internal/error.h

ractor.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "vm_core.h"
99
#include "vm_sync.h"
1010
#include "ractor_core.h"
11+
#include "internal/class.h"
1112
#include "internal/complex.h"
1213
#include "internal/error.h"
1314
#include "internal/gc.h"
@@ -1540,6 +1541,9 @@ mark_shareable(VALUE obj)
15401541
}
15411542

15421543
rb_obj_set_shareable_no_assert(obj);
1544+
if (RCLASS_SINGLETON_P(RBASIC(obj)->klass)) {
1545+
rb_obj_set_shareable_no_assert(RBASIC(obj)->klass);
1546+
}
15431547
return traverse_cont;
15441548
}
15451549

@@ -1587,9 +1591,14 @@ shareable_p_enter(VALUE obj)
15871591
else if (RB_TYPE_P(obj, T_CLASS) ||
15881592
RB_TYPE_P(obj, T_MODULE) ||
15891593
RB_TYPE_P(obj, T_ICLASS)) {
1590-
// TODO: remove it
1591-
mark_shareable(obj);
1592-
return traverse_skip;
1594+
if (RCLASS_SINGLETON_P(obj) && !RB_OBJ_SHAREABLE_P(RCLASS_ATTACHED_OBJECT(obj))) {
1595+
return traverse_stop;
1596+
}
1597+
else {
1598+
// TODO: remove it
1599+
mark_shareable(obj);
1600+
return traverse_skip;
1601+
}
15931602
}
15941603
else if (RB_OBJ_FROZEN_RAW(obj) &&
15951604
allow_frozen_shareable_p(obj)) {

0 commit comments

Comments
 (0)