🐛 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:
parent
af48a485e8
commit
27905d66de
@ -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
25
main.js
@ -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);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user