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>
This commit is contained in:
copilot-swe-agent[bot]
2026-03-05 13:17:56 +00:00
parent 2e242912af
commit 49b82a352b
2 changed files with 24 additions and 14 deletions

View File

@@ -88,18 +88,29 @@ export async function invokeWithTimeout<T>(
timeoutMs = INVOKE_TIMEOUT_MS timeoutMs = INVOKE_TIMEOUT_MS
): Promise<T> { ): Promise<T> {
return new Promise<T>((resolve, reject) => { return new Promise<T>((resolve, reject) => {
let settled = false;
const timer = setTimeout(() => { 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); }, timeoutMs);
(client.invoke(request) as Promise<T>) (client.invoke(request) as Promise<T>)
.then((result) => { .then((result) => {
clearTimeout(timer); if (!settled) {
resolve(result); settled = true;
clearTimeout(timer);
resolve(result);
}
}) })
.catch((err) => { .catch((err) => {
clearTimeout(timer); if (!settled) {
reject(err); settled = true;
clearTimeout(timer);
reject(err);
}
}); });
}); });
} }

View File

@@ -27,10 +27,6 @@ export async function withTdlibMutex<T>(
if (locked) { if (locked) {
log.info({ waiting: label, holder }, "Waiting for TDLib mutex"); log.info({ waiting: label, holder }, "Waiting for TDLib mutex");
await new Promise<void>((resolve, reject) => { await new Promise<void>((resolve, reject) => {
const entry = { resolve, reject, label };
queue.push(entry);
// Timeout: reject if we've been waiting too long
const timer = setTimeout(() => { const timer = setTimeout(() => {
const idx = queue.indexOf(entry); const idx = queue.indexOf(entry);
if (idx !== -1) { if (idx !== -1) {
@@ -42,12 +38,15 @@ export async function withTdlibMutex<T>(
} }
}, MUTEX_WAIT_TIMEOUT_MS); }, MUTEX_WAIT_TIMEOUT_MS);
// Wrap resolve to clear the timer const entry = {
const origResolve = entry.resolve; resolve: () => {
entry.resolve = () => { clearTimeout(timer);
clearTimeout(timer); resolve();
origResolve(); },
reject,
label,
}; };
queue.push(entry);
}); });
} }