diff --git a/main.js b/main.js index 91b63cc..fccc987 100644 --- a/main.js +++ b/main.js @@ -1270,6 +1270,13 @@ ipcMain.handle('start-upload', (_event, payload) => { } }); + // Capture the manager identity at listener-registration time so the post- + // batch null-out can compare against IT — not against whatever the global + // happens to point at after an `await`. Without this, a renderer that + // fires start-upload while we're still awaiting appendHistory would + // create a fresh manager which the trailing `uploadManager = null` then + // orphans (cancel/addJobs see null, the new batch keeps running invisibly). + const _thisManager = uploadManager; uploadManager.on('batch-done', async (summary) => { debugLog(`batch-done: total=${summary.total} ok=${summary.succeeded} fail=${summary.failed}`); logMemorySnapshot('batch-done'); @@ -1282,7 +1289,8 @@ ipcMain.handle('start-upload', (_event, payload) => { // Shutdown after finish handleShutdownAfterFinish(); - uploadManager = null; + if (uploadManager === _thisManager) uploadManager = null; + else debugLog('batch-done: skipping uploadManager null-out — a newer manager replaced this one mid-await'); }); // Defer startBatch to next tick so the IPC response is sent first. diff --git a/tasks/todo.md b/tasks/todo.md index b2e6767..9e05dbe 100644 --- a/tasks/todo.md +++ b/tasks/todo.md @@ -13,9 +13,16 @@ - ✅ 3.3.9 — Throttled-Cache nach `lib/throttled-cache.js` extrahiert (von sortQueueJobs dynamic-throttle genutzt) + 12 Unit-Tests (TTL-Boundary, identity-tracking, fake-clock, peek/clear, refreshMs=0, large-input) - ✅ 3.3.10 — `npm audit fix` (non-breaking): 4 vulnerabilities geschlossen (16 → 12), nur Lock-file Update - ✅ 3.3.11 — Patch-Bumps `eslint 10.1→10.2`, `undici 7.24→7.25`, `ws 8.19→8.20` (semver-compatible) +- ✅ 3.3.12 — Race condition fix: `uploadManager = null` in batch-done clobberte einen frisch gespawnten Manager wenn user mid-await neuen batch startete (deep-audit finding HIGH-1) ## Open items (priorisiert) +### Stabilität (neu aus deep-audit) +- [ ] `save-global-settings-sync` swallows write errors silently (main.js:1612-1628) — returns true even on disk-full / AV-lock. Should set returnValue=false + debugLog. +- [ ] `parseByseResult` / `parseDoodstreamResult` crash on null payload (lib/hosters.js:202, 214, 163, 491) — `JSON.parse('null')` returns null, then `payload.files` throws TypeError. Guard `if (!payload || typeof payload !== 'object') throw...` after JSON.parse. +- [ ] Cancellation latency in retry-loop's account-rotation block (lib/upload-manager.js:680-792) — re-check signal.aborted after each await. +- [ ] TOCTOU on backup write in `_atomicWrite` (lib/config-store.js:254-258) — readFileSync after existsSync without try/catch; can fail if AV briefly locks file. + ### Code-Qualität (deferred) - [ ] removeFromQueueOnDone microtask-coalesce (3.3.1) — Microtask-Timing schwer zu testen ohne fake-timer setup - [ ] 12 weitere Vulnerabilities (10 high, 2 low) in electron-builder dev-chain — bräuchten `npm audit fix --force` mit Major-Bump electron-builder@26.8.1 (breaking). Skip bis User explizit ein Major-Update erlaubt.