🐛 fix: shutdown countdown ignores mode change, timer leaks

Critical: handleShutdownAfterFinish() captured shutdown mode in a
closure at scheduling time — changing mode during countdown was ignored,
causing unexpected system shutdown/restart/sleep.

Now reads shutdownMode at execution time, clears timer when mode
changes to 'nothing', clears orphaned timers before creating new ones,
and adds error handling on exec() calls.

Also: guard stats timer against double-start in upload-manager.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Administrator 2026-03-21 13:19:07 +01:00
parent af48a485e8
commit 27905d66de
2 changed files with 18 additions and 8 deletions

View File

@ -550,6 +550,7 @@ class UploadManager extends EventEmitter {
}
_startStatsTimer() {
if (this.statsInterval) clearInterval(this.statsInterval);
this.statsInterval = setInterval(() => {
let globalSpeedKbs = 0;
let activeCount = 0;

25
main.js
View File

@ -1258,6 +1258,11 @@ let shutdownTimer = null;
ipcMain.handle('set-shutdown-after-finish', (_event, mode) => {
shutdownMode = mode || 'nothing';
// Cancel active countdown if mode changed to 'nothing'
if (shutdownMode === 'nothing' && shutdownTimer) {
clearTimeout(shutdownTimer);
shutdownTimer = null;
}
return true;
});
@ -1278,21 +1283,25 @@ function handleShutdownAfterFinish() {
if (shutdownMode === 'nothing') return;
const { exec } = require('child_process');
const mode = shutdownMode;
// Notify renderer
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.webContents.send('shutdown-countdown', { mode, seconds: 60 });
mainWindow.webContents.send('shutdown-countdown', { mode: shutdownMode, seconds: 60 });
}
// Clear any previous countdown to prevent orphaned timers
if (shutdownTimer) clearTimeout(shutdownTimer);
shutdownTimer = setTimeout(() => {
if (mode === 'shutdown') {
exec('shutdown /s /t 0');
} else if (mode === 'restart') {
exec('shutdown /r /t 0');
} else if (mode === 'sleep') {
exec('rundll32.exe powrprof.dll,SetSuspendState 0,1,0');
// Read current mode at execution time (not captured at scheduling time)
if (shutdownMode === 'shutdown') {
exec('shutdown /s /t 0', (err) => { if (err) debugLog(`shutdown failed: ${err.message}`); });
} else if (shutdownMode === 'restart') {
exec('shutdown /r /t 0', (err) => { if (err) debugLog(`restart failed: ${err.message}`); });
} else if (shutdownMode === 'sleep') {
exec('rundll32.exe powrprof.dll,SetSuspendState 0,1,0', (err) => { if (err) debugLog(`sleep failed: ${err.message}`); });
}
// else: mode was changed to 'nothing' during countdown — do nothing
}, 60000);
}