diff --git a/ext/mini_racer_extension/mini_racer_extension.c b/ext/mini_racer_extension/mini_racer_extension.c index 496d011..e3adfb8 100644 --- a/ext/mini_racer_extension/mini_racer_extension.c +++ b/ext/mini_racer_extension/mini_racer_extension.c @@ -1603,6 +1603,21 @@ void v8_get_flags(char **p, size_t *n) rb_thread_lock_native_thread(); } +// Blocks until the V8 thread finishes booting the isolate, which includes +// snapshot deserialization (v8::Isolate::New) and safe-context setup. None of +// that touches Ruby objects -- the snapshot is a plain C buffer already copied +// into |c->snapshot| -- so we release the GVL while waiting, letting other Ruby +// threads (e.g. a background pool refilling more contexts) truly run meanwhile. +static void *context_boot_wait(void *arg) +{ + Context *c; + + c = arg; + barrier_wait(&c->early_init); + barrier_wait(&c->late_init); + return NULL; +} + static VALUE context_initialize(int argc, VALUE *argv, VALUE self) { VALUE kwargs, a, k, v; @@ -1670,8 +1685,7 @@ static VALUE context_initialize(int argc, VALUE *argv, VALUE self) pthread_attr_destroy(&attr); if (r) goto fail; - barrier_wait(&c->early_init); - barrier_wait(&c->late_init); + rb_thread_call_without_gvl(context_boot_wait, c, NULL, NULL); } return Qnil; fail: