Skip to content

Commit b2370f6

Browse files
Fix missing Asyncify-loop on exposed entry points
Some of operations that *may* trigger Asyncify-unwind were not surrounded by the Asyncify-loop. Without the loop, the unwinding would not be stopped at the boundary of the guest function, and the continuation would be lost. Typically, unwinding for scanning GC root from Wasm locals were not rewound properly, then the GC would miss some objects and cause a crash.
1 parent f3a0599 commit b2370f6

File tree

1 file changed

+33
-15
lines changed

1 file changed

+33
-15
lines changed

packages/gems/js/ext/js/witapi-core.c

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,25 @@
33
#include "ruby.h"
44
#include "ruby/version.h"
55

6-
static VALUE rb_eval_string_value_protect_thunk(VALUE str) {
6+
#include "types.h"
7+
8+
static VALUE rb_eval_string_value_protect_thunk(VALUE ctx) {
9+
const rb_abi_guest_string_t *cabi_str = (const rb_abi_guest_string_t *)ctx;
10+
VALUE str = rb_utf8_str_new((const char *)cabi_str->ptr, cabi_str->len);
711
const ID id_eval = rb_intern("eval");
812
VALUE binding = rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING"));
913
const VALUE file = rb_utf8_str_new("eval", 4);
1014
VALUE args[3] = {str, binding, file};
1115
return rb_funcallv(rb_mKernel, id_eval, 3, args);
1216
}
1317

14-
static VALUE rb_eval_string_value_protect(VALUE str, int *pstate) {
15-
return rb_protect(rb_eval_string_value_protect_thunk, str, pstate);
18+
static VALUE rb_eval_string_value_protect(const rb_abi_guest_string_t *str,
19+
int *pstate) {
20+
return rb_protect(rb_eval_string_value_protect_thunk, (VALUE)str, pstate);
1621
}
1722

1823
#define TAG_NONE 0
1924

20-
#include "types.h"
21-
2225
__attribute__((import_module("asyncify"), import_name("start_unwind"))) void
2326
asyncify_start_unwind(void *buf);
2427
#define asyncify_start_unwind(buf) \
@@ -200,15 +203,17 @@ void exports_ruby_js_ruby_runtime_rb_abi_value_destructor(
200203

201204
void rb_abi_guest_ruby_show_version(void) { ruby_show_version(); }
202205

203-
void rb_abi_guest_ruby_init(void) {
204-
RB_WASM_LIB_RT(ruby_init())
205-
206+
__attribute__((noinline)) static void rb_abi_guest_ruby_init_thunk(void) {
207+
ruby_init();
206208
rb_abi_guest_arena_hash = rb_hash_new();
207209
rb_abi_guest_refcount_hash = rb_hash_new();
208210

209211
rb_gc_register_mark_object(rb_abi_guest_arena_hash);
210212
rb_gc_register_mark_object(rb_abi_guest_refcount_hash);
211213
}
214+
void rb_abi_guest_ruby_init(void) {
215+
RB_WASM_LIB_RT(rb_abi_guest_ruby_init_thunk())
216+
}
212217

213218
void rb_abi_guest_ruby_sysinit(rb_abi_guest_list_string_t *args) {
214219
char **c_args;
@@ -234,12 +239,11 @@ void rb_abi_guest_ruby_init_loadpath(void) {
234239
RB_WASM_LIB_RT(ruby_init_loadpath())
235240
}
236241

237-
void rb_abi_guest_rb_eval_string_protect(
242+
__attribute__((noinline)) static void rb_abi_guest_rb_eval_string_protect_thunk(
238243
rb_abi_guest_string_t *str, rb_abi_guest_tuple2_rb_abi_value_s32_t *ret0) {
239244
VALUE retval;
240245
RB_WASM_DEBUG_LOG("rb_eval_string_protect: str = %s\n", str->ptr);
241-
VALUE utf8_str = rb_utf8_str_new((const char *)str->ptr, str->len);
242-
RB_WASM_LIB_RT(retval = rb_eval_string_value_protect(utf8_str, &ret0->f1));
246+
retval = rb_eval_string_value_protect(str, &ret0->f1);
243247
RB_WASM_DEBUG_LOG("rb_eval_string_protect: retval = %p, state = %d\n",
244248
(void *)retval, ret0->f1);
245249

@@ -248,6 +252,10 @@ void rb_abi_guest_rb_eval_string_protect(
248252
}
249253
ret0->f0 = rb_abi_guest_rb_abi_value_new((void *)retval);
250254
}
255+
void rb_abi_guest_rb_eval_string_protect(
256+
rb_abi_guest_string_t *str, rb_abi_guest_tuple2_rb_abi_value_s32_t *ret0) {
257+
RB_WASM_LIB_RT(rb_abi_guest_rb_eval_string_protect_thunk(str, ret0));
258+
}
251259

252260
struct rb_funcallv_thunk_ctx {
253261
VALUE recv;
@@ -284,7 +292,9 @@ void rb_abi_guest_rb_funcallv_protect(
284292
}
285293

286294
rb_abi_guest_rb_id_t rb_abi_guest_rb_intern(rb_abi_guest_string_t *name) {
287-
return rb_intern((const char *)name->ptr);
295+
VALUE retval;
296+
RB_WASM_LIB_RT(retval = rb_intern((const char *)name->ptr));
297+
return (rb_abi_guest_rb_id_t)retval;
288298
}
289299

290300
rb_abi_guest_own_rb_abi_value_t rb_abi_guest_rb_errinfo(void) {
@@ -294,16 +304,24 @@ rb_abi_guest_own_rb_abi_value_t rb_abi_guest_rb_errinfo(void) {
294304
return rb_abi_guest_rb_abi_value_new((void *)retval);
295305
}
296306

297-
void rb_abi_guest_rb_clear_errinfo(void) { rb_set_errinfo(Qnil); }
307+
void rb_abi_guest_rb_clear_errinfo(void) {
308+
RB_WASM_LIB_RT(rb_set_errinfo(Qnil));
309+
}
298310

299-
void rb_abi_guest_rstring_ptr(rb_abi_guest_rb_abi_value_t value,
300-
rb_abi_guest_string_t *ret0) {
311+
__attribute__((noinline)) static void
312+
rb_abi_guest_rstring_ptr_thunk(rb_abi_guest_rb_abi_value_t value,
313+
rb_abi_guest_string_t *ret0) {
301314
VALUE r_str = (VALUE)rb_abi_guest_rb_abi_value_get(&value);
302315
ret0->len = RSTRING_LEN(r_str);
303316
ret0->ptr = xmalloc(ret0->len);
304317
memcpy(ret0->ptr, RSTRING_PTR(r_str), ret0->len);
305318
}
306319

320+
void rb_abi_guest_rstring_ptr(rb_abi_guest_rb_abi_value_t value,
321+
rb_abi_guest_string_t *ret0) {
322+
RB_WASM_LIB_RT(rb_abi_guest_rstring_ptr_thunk(value, ret0));
323+
}
324+
307325
uint32_t rb_abi_guest_rb_abi_value_data_ptr(rb_abi_guest_rb_abi_value_t self) {
308326
VALUE obj = (VALUE)rb_abi_guest_rb_abi_value_get(&self);
309327
return (uint32_t)DATA_PTR(obj);

0 commit comments

Comments
 (0)