From 7335c7f10a80039c4444152588b3481e02bdc004 Mon Sep 17 00:00:00 2001 From: David Taylor Date: Mon, 10 Aug 2026 17:12:13 +0000 Subject: [PATCH] FIX: don't drop requests that arrive before v8_roundtrip is re-entered When an attached Ruby callback makes its own request on the same context (perform_microtask_checkpoint, a nested call, etc), the Ruby thread can enqueue its next request in the gap between the nested dispatch finishing and the V8 thread re-entering v8_roundtrip. The buf_reset(&c->req) on entry then destroyed that request, leaving both threads waiting on each other forever. The reset is a leftover from before 478c763, when v8_roundtrip returned a pointer into the live request buffer and had to clear it on the next entry. Requests are now handed off with buf_move, so the buffer is already empty on re-entry unless it holds a new, unread message. --- CHANGELOG | 3 +++ ext/mini_racer_extension/mini_racer_extension.c | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index d1c5c44..ec96172 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +- Unreleased + - Fix a race introduced in 0.21.4 where a request sent right after a nested dispatch (e.g. `perform_microtask_checkpoint` or a nested `call` from an attached callback) could be dropped, deadlocking the context + - 0.21.4 - 24-06-2026 - Fix stale V8 termination state after interrupts/timeouts so contexts remain usable after cancelled evaluations - Let Ruby interrupts wake MiniRacer calls without immediately terminating V8, allowing signal traps and nested callbacks to unwind safely diff --git a/ext/mini_racer_extension/mini_racer_extension.c b/ext/mini_racer_extension/mini_racer_extension.c index afa6e9d..c13dbfe 100644 --- a/ext/mini_racer_extension/mini_racer_extension.c +++ b/ext/mini_racer_extension/mini_racer_extension.c @@ -893,7 +893,6 @@ void v8_roundtrip(Context *c, const uint8_t **p, size_t *n) { pthread_mutex_lock(&c->mtx); buf_reset(&c->v8_req); - buf_reset(&c->req); if (c->res.len) c->res_ready = 1; pthread_cond_signal(&c->cv);