@mytec: iter2.3 multithreading p1 done

This commit is contained in:
2026-01-31 20:54:14 +02:00
parent 26f8067c94
commit 3b010fed83
10 changed files with 937 additions and 27 deletions

View File

@@ -8,7 +8,9 @@ const store = new Store();
let mainWindow;
let splashWindow;
let backendProcess;
let backendPid = null; // Store PID separately — survives even if backendProcess ref is lost
let backendLogStream;
let isQuitting = false;
// ── Paths ──────────────────────────────────────────────────────────
@@ -184,6 +186,10 @@ async function startBackend() {
});
}
// Store PID immediately
backendPid = backendProcess.pid;
log(`Backend PID: ${backendPid}`);
// Pipe backend output to log
const backendLogFile = path.join(logDir, 'rfcp-backend.log');
const backendLog = fs.createWriteStream(backendLogFile, { flags: 'w' });
@@ -262,10 +268,15 @@ function createMainWindow() {
titleBarStyle: process.platform === 'darwin' ? 'hiddenInset' : 'default',
});
// Save window state on close
// Save window state on close and trigger shutdown
mainWindow.on('close', () => {
const bounds = mainWindow.getBounds();
store.set('windowState', bounds);
try {
const bounds = mainWindow.getBounds();
store.set('windowState', bounds);
} catch (_e) {}
log('Main window closing — killing backend');
isQuitting = true;
killBackend();
});
// Load frontend
@@ -309,28 +320,33 @@ function createMainWindow() {
// ── Backend cleanup ───────────────────────────────────────────────
function killBackend() {
if (!backendProcess) return;
const pid = backendPid || backendProcess?.pid;
if (!pid) return;
const pid = backendProcess.pid;
log(`Killing backend (PID ${pid})...`);
try {
if (process.platform === 'win32') {
// Windows: taskkill with /T (tree) to kill child processes too
execSync(`taskkill /f /t /pid ${pid}`, { stdio: 'ignore' });
// Windows: taskkill with /F (force) /T (tree kills child processes too)
execSync(`taskkill /F /T /PID ${pid}`, { stdio: 'ignore' });
} else {
// Unix: kill process group
process.kill(-pid, 'SIGTERM');
try {
process.kill(-pid, 'SIGTERM');
} catch (_e) {
process.kill(pid, 'SIGTERM');
}
}
} catch (e) {
// Fallback: try normal kill
// Fallback: try normal kill via process handle
try {
backendProcess.kill('SIGKILL');
backendProcess?.kill('SIGKILL');
} catch (_e2) {
// Already dead
// Already dead — that's fine
}
}
backendPid = null;
backendProcess = null;
log('Backend killed');
}
@@ -365,6 +381,8 @@ app.whenReady().then(async () => {
});
app.on('window-all-closed', () => {
log('Event: window-all-closed');
isQuitting = true;
killBackend();
if (process.platform !== 'darwin') {
@@ -379,14 +397,36 @@ app.on('activate', () => {
});
app.on('before-quit', () => {
log('Event: before-quit');
isQuitting = true;
killBackend();
});
app.on('will-quit', () => {
log('Event: will-quit');
killBackend();
if (backendLogStream) {
backendLogStream.end();
try { backendLogStream.end(); } catch (_e) {}
backendLogStream = null;
}
});
// Last resort: ensure backend is killed when Node process exits
process.on('exit', () => {
if (backendPid) {
try {
if (process.platform === 'win32') {
execSync(`taskkill /F /T /PID ${backendPid}`, { stdio: 'ignore' });
} else {
process.kill(backendPid, 'SIGKILL');
}
} catch (_e) {
// Best effort
}
}
});
// ── IPC Handlers ───────────────────────────────────────────────────
ipcMain.handle('get-data-path', () => getDataPath());