Skip to content

Commit 1f4242d

Browse files
committed
Get transcoding to work across ractors by locking certain operations
Ex: `str.encode` and `str.encode!` work across ractors now. I'm not certain that these are all the locks we need, there may be more that I missed. However, it's certainly a lot better than before. I'm not getting anymore segfaults or encoding not found exceptions when running tests inside multiple ractors.
1 parent 5ec9a39 commit 1f4242d

File tree

1 file changed

+58
-36
lines changed

1 file changed

+58
-36
lines changed

transcode.c

Lines changed: 58 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "internal/string.h"
2121
#include "internal/transcode.h"
2222
#include "ruby/encoding.h"
23+
#include "vm_sync.h"
2324

2425
#include "transcode_data.h"
2526
#include "id.h"
@@ -209,19 +210,21 @@ make_transcoder_entry(const char *sname, const char *dname)
209210
st_data_t val;
210211
st_table *table2;
211212

212-
if (!st_lookup(transcoder_table, (st_data_t)sname, &val)) {
213-
val = (st_data_t)st_init_strcasetable();
214-
st_add_direct(transcoder_table, (st_data_t)sname, val);
215-
}
216-
table2 = (st_table *)val;
217-
if (!st_lookup(table2, (st_data_t)dname, &val)) {
218-
transcoder_entry_t *entry = ALLOC(transcoder_entry_t);
219-
entry->sname = sname;
220-
entry->dname = dname;
221-
entry->lib = NULL;
222-
entry->transcoder = NULL;
223-
val = (st_data_t)entry;
224-
st_add_direct(table2, (st_data_t)dname, val);
213+
RB_VM_LOCKING() {
214+
if (!st_lookup(transcoder_table, (st_data_t)sname, &val)) {
215+
val = (st_data_t)st_init_strcasetable();
216+
st_add_direct(transcoder_table, (st_data_t)sname, val);
217+
}
218+
table2 = (st_table *)val;
219+
if (!st_lookup(table2, (st_data_t)dname, &val)) {
220+
transcoder_entry_t *entry = ALLOC(transcoder_entry_t);
221+
entry->sname = sname;
222+
entry->dname = dname;
223+
entry->lib = NULL;
224+
entry->transcoder = NULL;
225+
val = (st_data_t)entry;
226+
st_add_direct(table2, (st_data_t)dname, val);
227+
}
225228
}
226229
return (transcoder_entry_t *)val;
227230
}
@@ -231,14 +234,18 @@ get_transcoder_entry(const char *sname, const char *dname)
231234
{
232235
st_data_t val;
233236
st_table *table2;
234-
237+
unsigned int lev;
238+
RB_VM_LOCK_ENTER_LEV(&lev);
235239
if (!st_lookup(transcoder_table, (st_data_t)sname, &val)) {
240+
RB_VM_LOCK_LEAVE_LEV(&lev);
236241
return NULL;
237242
}
238243
table2 = (st_table *)val;
239244
if (!st_lookup(table2, (st_data_t)dname, &val)) {
245+
RB_VM_LOCK_LEAVE_LEV(&lev);
240246
return NULL;
241247
}
248+
RB_VM_LOCK_LEAVE_LEV(&lev);
242249
return (transcoder_entry_t *)val;
243250
}
244251

@@ -249,14 +256,19 @@ rb_register_transcoder(const rb_transcoder *tr)
249256
const char *const dname = tr->dst_encoding;
250257

251258
transcoder_entry_t *entry;
259+
unsigned int lev;
252260

253-
entry = make_transcoder_entry(sname, dname);
254-
if (entry->transcoder) {
255-
rb_raise(rb_eArgError, "transcoder from %s to %s has been already registered",
256-
sname, dname);
261+
RB_VM_LOCK_ENTER_LEV(&lev);
262+
{
263+
entry = make_transcoder_entry(sname, dname);
264+
if (entry->transcoder) {
265+
RB_VM_LOCK_LEAVE_LEV(&lev);
266+
rb_raise(rb_eArgError, "transcoder from %s to %s has been already registered",
267+
sname, dname);
268+
}
269+
entry->transcoder = tr;
257270
}
258-
259-
entry->transcoder = tr;
271+
RB_VM_LOCK_LEAVE_LEV(&lev);
260272
}
261273

262274
static void
@@ -325,6 +337,7 @@ transcode_search_path(const char *sname, const char *dname,
325337
st_table *table2;
326338
int found;
327339
int pathlen = -1;
340+
bool lookup_res;
328341

329342
if (encoding_equal(sname, dname))
330343
return -1;
@@ -344,7 +357,11 @@ transcode_search_path(const char *sname, const char *dname,
344357
if (!bfs.queue)
345358
bfs.queue_last_ptr = &bfs.queue;
346359

347-
if (!st_lookup(transcoder_table, (st_data_t)q->enc, &val)) {
360+
RB_VM_LOCKING() {
361+
lookup_res = st_lookup(transcoder_table, (st_data_t)q->enc, &val);
362+
}
363+
364+
if (!lookup_res) {
348365
xfree(q);
349366
continue;
350367
}
@@ -2662,23 +2679,28 @@ rb_econv_open_opts(const char *source_encoding, const char *destination_encoding
26622679
replacement = rb_hash_aref(opthash, sym_replace);
26632680
}
26642681

2665-
ec = rb_econv_open(source_encoding, destination_encoding, ecflags);
2666-
if (!ec)
2667-
return ec;
2668-
2669-
if (!NIL_P(replacement)) {
2670-
int ret;
2671-
rb_encoding *enc = rb_enc_get(replacement);
2672-
2673-
ret = rb_econv_set_replacement(ec,
2674-
(const unsigned char *)RSTRING_PTR(replacement),
2675-
RSTRING_LEN(replacement),
2676-
rb_enc_name(enc));
2677-
if (ret == -1) {
2678-
rb_econv_close(ec);
2679-
return NULL;
2682+
unsigned int lev;
2683+
RB_VM_LOCK_ENTER_LEV(&lev);
2684+
{
2685+
ec = rb_econv_open(source_encoding, destination_encoding, ecflags);
2686+
if (ec) {
2687+
if (!NIL_P(replacement)) {
2688+
int ret;
2689+
rb_encoding *enc = rb_enc_get(replacement);
2690+
2691+
ret = rb_econv_set_replacement(ec,
2692+
(const unsigned char *)RSTRING_PTR(replacement),
2693+
RSTRING_LEN(replacement),
2694+
rb_enc_name(enc));
2695+
if (ret == -1) {
2696+
rb_econv_close(ec);
2697+
RB_VM_LOCK_LEAVE_LEV(&lev);
2698+
return NULL;
2699+
}
2700+
}
26802701
}
26812702
}
2703+
RB_VM_LOCK_LEAVE_LEV(&lev);
26822704
return ec;
26832705
}
26842706

0 commit comments

Comments
 (0)