fix(socket): move PreKey sync reschedule check inside finally block

Minimizes race window between isRunning=false and reschedule check by
moving the setTimeout reschedule logic inside the finally block.

Changes:
- Move reschedule check (if !closed && !cleanedUp && ws.isOpen) from
  after finally block to inside finally block
- Reduces race window where end() could be called between finally and check

Timeline before fix:
T0: syncLoop finally executes → isRunning = false
T1: end() called → closed = true
T2: syncLoop checks if (!closed) ← sees false
T3: setTimeout scheduled ← orphaned timer
T4: cleanupPreKeyAutoSync() clears it

Timeline after fix:
T0: syncLoop finally executes → isRunning = false
T1: Immediately checks flags INSIDE finally (atomic)
T2: Window too small for race condition

Risk: LOW (cleanup function already handles orphaned timers)
Impact: Cleaner code, minimizes theoretical race window

https://claude.ai/code/session_VMxqX
This commit is contained in:
Claude
2026-02-04 03:11:41 +00:00
parent 08cad354a7
commit f2e9701b9c
+5 -5
View File
@@ -766,12 +766,12 @@ export const makeSocket = (config: SocketConfig) => {
logger.error({ error }, '🔑 PreKey auto-sync failed')
} finally {
isRunning = false
}
// PROTECTION 3: Prevent timer accumulation and post-cleanup rescheduling
// Check cleanedUp flag atomically to prevent race condition
if (!closed && !cleanedUp && ws.isOpen) {
syncTimer = setTimeout(syncLoop, SYNC_INTERVAL)
// PROTECTION 3: Prevent timer accumulation and post-cleanup rescheduling
// Check cleanedUp flag atomically INSIDE finally to minimize race window
if (!closed && !cleanedUp && ws.isOpen) {
syncTimer = setTimeout(syncLoop, SYNC_INTERVAL)
}
}
}