From 49b82a352bc2c91abae06aeb658657758f9268df Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Mar 2026 13:17:56 +0000 Subject: [PATCH] Fix review issues: race condition in invokeWithTimeout and mutex queue entry - Add settled flag to invokeWithTimeout to prevent double-settling - Create mutex queue entry with wrapped resolve before pushing to queue Co-authored-by: xCyanGrizzly <53275238+xCyanGrizzly@users.noreply.github.com> --- worker/src/tdlib/download.ts | 21 ++++++++++++++++----- worker/src/util/mutex.ts | 17 ++++++++--------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/worker/src/tdlib/download.ts b/worker/src/tdlib/download.ts index d9c4a88..600c7d7 100644 --- a/worker/src/tdlib/download.ts +++ b/worker/src/tdlib/download.ts @@ -88,18 +88,29 @@ export async function invokeWithTimeout( timeoutMs = INVOKE_TIMEOUT_MS ): Promise { return new Promise((resolve, reject) => { + let settled = false; + const timer = setTimeout(() => { - reject(new Error(`TDLib invoke timed out after ${timeoutMs}ms for ${request._}`)); + if (!settled) { + settled = true; + reject(new Error(`TDLib invoke timed out after ${timeoutMs}ms for ${request._}`)); + } }, timeoutMs); (client.invoke(request) as Promise) .then((result) => { - clearTimeout(timer); - resolve(result); + if (!settled) { + settled = true; + clearTimeout(timer); + resolve(result); + } }) .catch((err) => { - clearTimeout(timer); - reject(err); + if (!settled) { + settled = true; + clearTimeout(timer); + reject(err); + } }); }); } diff --git a/worker/src/util/mutex.ts b/worker/src/util/mutex.ts index dcb95cf..e559318 100644 --- a/worker/src/util/mutex.ts +++ b/worker/src/util/mutex.ts @@ -27,10 +27,6 @@ export async function withTdlibMutex( if (locked) { log.info({ waiting: label, holder }, "Waiting for TDLib mutex"); await new Promise((resolve, reject) => { - const entry = { resolve, reject, label }; - queue.push(entry); - - // Timeout: reject if we've been waiting too long const timer = setTimeout(() => { const idx = queue.indexOf(entry); if (idx !== -1) { @@ -42,12 +38,15 @@ export async function withTdlibMutex( } }, MUTEX_WAIT_TIMEOUT_MS); - // Wrap resolve to clear the timer - const origResolve = entry.resolve; - entry.resolve = () => { - clearTimeout(timer); - origResolve(); + const entry = { + resolve: () => { + clearTimeout(timer); + resolve(); + }, + reject, + label, }; + queue.push(entry); }); }