summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootstraptest/test_ractor.rb17
-rw-r--r--class.c28
2 files changed, 32 insertions, 13 deletions
diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb
index 19a6e16302..5bf697a5d0 100644
--- a/bootstraptest/test_ractor.rb
+++ b/bootstraptest/test_ractor.rb
@@ -2259,3 +2259,20 @@ rescue NotImplementedError
:ok
end
}
+
+# Creating classes inside of Ractors
+# [Bug #18119]
+assert_equal 'ok', %q{
+ workers = (0...8).map do
+ Ractor.new do
+ loop do
+ 100.times.map { Class.new }
+ Ractor.yield nil
+ end
+ end
+ end
+
+ 100.times { Ractor.select(*workers) }
+
+ 'ok'
+}
diff --git a/class.c b/class.c
index dca3bacf7e..7d7304faf6 100644
--- a/class.c
+++ b/class.c
@@ -83,23 +83,25 @@ RUBY_EXTERN rb_serial_t ruby_vm_global_cvar_state;
static rb_subclass_entry_t *
push_subclass_entry_to_list(VALUE super, VALUE klass)
{
- rb_subclass_entry_t *entry, *head;
-
- entry = ZALLOC(rb_subclass_entry_t);
+ rb_subclass_entry_t *entry = ZALLOC(rb_subclass_entry_t);
entry->klass = klass;
- head = RCLASS_SUBCLASSES(super);
- if (!head) {
- head = ZALLOC(rb_subclass_entry_t);
- RCLASS_SUBCLASSES(super) = head;
- }
- entry->next = head->next;
- entry->prev = head;
+ RB_VM_LOCK_ENTER();
+ {
+ rb_subclass_entry_t *head = RCLASS_SUBCLASSES(super);
+ if (!head) {
+ head = ZALLOC(rb_subclass_entry_t);
+ RCLASS_SUBCLASSES(super) = head;
+ }
+ entry->next = head->next;
+ entry->prev = head;
- if (head->next) {
- head->next->prev = entry;
+ if (head->next) {
+ head->next->prev = entry;
+ }
+ head->next = entry;
}
- head->next = entry;
+ RB_VM_LOCK_LEAVE();
return entry;
}