Skip to content

Commit e7ca42b

Browse files
committed
encoding.c: Acquire VM lock around require_silent_safe
`require_silent_safe` calls into `features_index_add` and a few other routines that need to be synchronized. There are other Ractor related concerns with autoloaded encodings but this one is the biggest.
1 parent 5564e0a commit e7ca42b

3 files changed

Lines changed: 53 additions & 7 deletions

File tree

encoding.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -725,12 +725,38 @@ rb_enc_get_from_index(int index)
725725

726726
int rb_require_internal_silent(VALUE fname);
727727

728+
static VALUE
729+
require_silent_safe(VALUE fname)
730+
{
731+
return INT2NUM(rb_require_internal_silent(fname));
732+
}
733+
734+
static int
735+
require_silent_sync(VALUE fname)
736+
{
737+
int state;
738+
VALUE retval;
739+
RB_VM_LOCKING() {
740+
VALUE debug = ruby_debug;
741+
VALUE errinfo = rb_errinfo();
742+
743+
ruby_debug = Qfalse;
744+
745+
retval = rb_protect(require_silent_safe, fname, &state);
746+
747+
ruby_debug = debug;
748+
rb_set_errinfo(errinfo);
749+
}
750+
if (state) {
751+
rb_jump_tag(state);
752+
}
753+
return NUM2INT(retval);
754+
}
755+
728756
static int
729757
load_encoding(const char *name)
730758
{
731759
VALUE enclib = rb_sprintf("enc/%s.so", name);
732-
VALUE debug = ruby_debug;
733-
VALUE errinfo;
734760
char *s = RSTRING_PTR(enclib) + 4, *e = RSTRING_END(enclib) - 3;
735761
int loaded;
736762
int idx;
@@ -741,11 +767,7 @@ load_encoding(const char *name)
741767
++s;
742768
}
743769
enclib = rb_fstring(enclib);
744-
ruby_debug = Qfalse;
745-
errinfo = rb_errinfo();
746-
loaded = rb_require_internal_silent(enclib);
747-
ruby_debug = debug;
748-
rb_set_errinfo(errinfo);
770+
loaded = require_silent_sync(enclib);
749771

750772
GLOBAL_ENC_TABLE_LOCKING(enc_table) {
751773
if (loaded < 0 || 1 < loaded) {

load.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "ruby/util.h"
2323
#include "ractor_core.h"
2424
#include "vm_core.h"
25+
#include "vm_sync.h"
2526

2627
static VALUE ruby_dln_libmap;
2728

@@ -372,6 +373,8 @@ features_index_add_single(vm_ns_t *vm_ns, const char* str, size_t len, VALUE off
372373
static void
373374
features_index_add(vm_ns_t *vm_ns, VALUE feature, VALUE offset)
374375
{
376+
ASSERT_vm_locking();
377+
375378
const char *feature_str, *feature_end, *ext, *p;
376379
bool rb = false;
377380

test/ruby/test_encoding.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,25 @@ def test_ractor_load_encoding
136136
assert "[Bug #19562]"
137137
end;
138138
end
139+
140+
def test_ractor_lazy_load_encoding_concurrently
141+
assert_ractor("#{<<~"begin;"}\n#{<<~'end;'}")
142+
begin;
143+
rs = []
144+
autoload_encodings = Encoding.list.select { |e| e.inspect.include?("(autoload)") }.freeze
145+
7.times do
146+
rs << Ractor.new(autoload_encodings) do |encodings|
147+
str = "abc".dup
148+
encodings.each do |enc|
149+
str.force_encoding(enc)
150+
end
151+
end
152+
end
153+
while rs.any?
154+
r, _obj = Ractor.select(*rs)
155+
rs.delete(r)
156+
end
157+
assert rs.empty?
158+
end;
159+
end
139160
end

0 commit comments

Comments
 (0)