fix: 修复关闭软件后 OpenCode 进程泄漏问题

- 使用 taskkill /F /T 强制终止进程树
- 在 before-quit 中 await 等待服务停止完成
- 修复 stop 方法中可能的空指针问题
This commit is contained in:
2026-03-16 13:11:46 +08:00
parent dcd1fcd709
commit 308df54a15
2 changed files with 54 additions and 14 deletions

View File

@@ -17,11 +17,20 @@ const __dirname = path.dirname(__filename);
electronState.setDevelopment(!app.isPackaged); electronState.setDevelopment(!app.isPackaged);
let lastClipboardText = ''; let lastClipboardText = '';
let clipboardWatcherTimer: NodeJS.Timeout | null = null;
function stopClipboardWatcher() {
if (clipboardWatcherTimer) {
clearInterval(clipboardWatcherTimer);
clipboardWatcherTimer = null;
log.info('[ClipboardWatcher] Stopped');
}
}
function startClipboardWatcher() { function startClipboardWatcher() {
lastClipboardText = clipboard.readText(); lastClipboardText = clipboard.readText();
setInterval(() => { clipboardWatcherTimer = setInterval(() => {
try { try {
const currentText = clipboard.readText(); const currentText = clipboard.readText();
if (currentText && currentText !== lastClipboardText) { if (currentText && currentText !== lastClipboardText) {
@@ -447,7 +456,26 @@ app.whenReady().then(async () => {
app.on('window-all-closed', () => { app.on('window-all-closed', () => {
globalShortcut.unregisterAll(); globalShortcut.unregisterAll();
opencodeService.stop(); opencodeService.stop();
xcOpenCodeWebService.stop();
stopClipboardWatcher();
if (process.platform !== 'darwin') { if (process.platform !== 'darwin') {
app.quit(); app.quit();
} }
}); });
let isQuitting = false;
app.on('before-quit', async (event) => {
if (isQuitting) return;
isQuitting = true;
log.info('[App] before-quit received, cleaning up...');
stopClipboardWatcher();
await Promise.all([
opencodeService.stop(),
xcOpenCodeWebService.stop()
]);
log.info('[App] All services stopped');
});

View File

@@ -1,4 +1,4 @@
import { spawn, ChildProcess } from 'child_process'; import { spawn, exec, ChildProcess } from 'child_process';
import log from 'electron-log'; import log from 'electron-log';
const OPENCODE_PORT = 4096; const OPENCODE_PORT = 4096;
@@ -150,21 +150,33 @@ class OpenCodeService {
try { try {
log.info('[OpenCodeService] Stopping...'); log.info('[OpenCodeService] Stopping...');
this.process.kill('SIGTERM'); const pid = this.process.pid;
await new Promise<void>((resolve) => {
setTimeout(resolve, 1000);
});
if (this.process && !this.process.killed) {
this.process.kill('SIGKILL');
}
this.process = null; this.process = null;
this._isRunning = false; this._isRunning = false;
this.restartAttempts = 0;
log.info('[OpenCodeService] Stopped'); if (pid && process.platform === 'win32') {
return new Promise((resolve) => {
exec(`taskkill /F /T /PID ${pid}`, (error) => {
if (error) {
log.warn('[OpenCodeService] taskkill failed, process may already be dead:', error.message);
}
this.restartAttempts = 0;
log.info('[OpenCodeService] Stopped');
resolve({ success: true });
});
});
} else if (pid) {
this.process?.kill('SIGTERM');
await new Promise<void>((resolve) => setTimeout(resolve, 1000));
if (this.process && !this.process.killed) {
this.process.kill('SIGKILL');
}
this.restartAttempts = 0;
log.info('[OpenCodeService] Stopped');
return { success: true };
}
this.restartAttempts = 0;
return { success: true }; return { success: true };
} catch (error: any) { } catch (error: any) {
log.error('[OpenCodeService] Failed to stop:', error); log.error('[OpenCodeService] Failed to stop:', error);