fix: Bridge OOM-Crash — Handler defensiv + Node-Heap 4GB [appimage]
Some checks failed
Build AppImage / build (push) Has been cancelled
Some checks failed
Build AppImage / build (push) Has been cancelled
Der uncaughtException-Handler aus f69f566 las err.stack dreimal und
serialisierte ihn zweimal per JSON.stringify. err.stack ist ein lazy
Getter der bei jedem Zugriff neu formatiert wird — bei V8-nahe-OOM
hat genau das den Abort ausgelöst (Crash-Dump Frames 20-24:
ErrorStackGetter → FormatStackTrace → FatalProcessOutOfMemory).
- Handler: err.stack einmal lesen, auf 2000 Zeichen kürzen, try/catch
drumrum. Handler darf nicht selbst crashen.
- Bridge-Start: --max-old-space-size=4096 (Node-Default ~2GB reicht
bei langen Sessions mit großen Thinking-Blocks + Agent-SDK-History
nicht). Betrifft Daemon- UND stdio-Modus.
This commit is contained in:
parent
94c7b9358d
commit
48c7b2a30c
2 changed files with 34 additions and 7 deletions
|
|
@ -1089,16 +1089,39 @@ process.on('SIGINT', () => { clearInterval(keepAlive); cleanupDaemon(); process.
|
|||
process.on('exit', () => { cleanupDaemon(); });
|
||||
|
||||
// Globale Fehler-Handler — Bridge darf nicht still abstürzen
|
||||
// WICHTIG: err.stack ist ein lazy Getter der bei jedem Zugriff neu formatiert wird
|
||||
// und bei V8-OOM selbst einen OOM-Abort auslösen kann. Daher: einmal lesen, kürzen,
|
||||
// try/catch drumrum — der Handler darf nicht selbst crashen.
|
||||
function safeStack(err) {
|
||||
try {
|
||||
const raw = (err && err.stack) ? String(err.stack) : '';
|
||||
return raw.length > 2000 ? raw.slice(0, 2000) + '\n...[gekürzt]' : raw;
|
||||
} catch {
|
||||
return '[stack nicht lesbar]';
|
||||
}
|
||||
}
|
||||
process.on('uncaughtException', (err) => {
|
||||
process.stderr.write(`❌ Unbehandelter Fehler: ${err.message}\n${err.stack}\n`);
|
||||
sendEvent('bridge-error', { type: 'uncaughtException', message: err.message, stack: err.stack });
|
||||
sendMonitorEvent('error', `Bridge Crash: ${err.message}`, { stack: err.stack });
|
||||
try {
|
||||
const msg = (err && err.message) ? String(err.message).slice(0, 500) : String(err).slice(0, 500);
|
||||
const stack = safeStack(err);
|
||||
process.stderr.write(`❌ Unbehandelter Fehler: ${msg}\n${stack}\n`);
|
||||
sendEvent('bridge-error', { type: 'uncaughtException', message: msg, stack });
|
||||
sendMonitorEvent('error', `Bridge Crash: ${msg}`, {});
|
||||
} catch (inner) {
|
||||
try { process.stderr.write(`❌ Handler-Fehler: ${inner && inner.message}\n`); } catch {}
|
||||
}
|
||||
});
|
||||
process.on('unhandledRejection', (reason) => {
|
||||
const msg = reason instanceof Error ? reason.message : String(reason);
|
||||
try {
|
||||
const msg = reason instanceof Error
|
||||
? String(reason.message).slice(0, 500)
|
||||
: String(reason).slice(0, 500);
|
||||
process.stderr.write(`❌ Unhandled Promise Rejection: ${msg}\n`);
|
||||
sendEvent('bridge-error', { type: 'unhandledRejection', message: msg });
|
||||
sendMonitorEvent('error', `Unhandled Rejection: ${msg}`, {});
|
||||
} catch (inner) {
|
||||
try { process.stderr.write(`❌ Handler-Fehler: ${inner && inner.message}\n`); } catch {}
|
||||
}
|
||||
});
|
||||
|
||||
// Bereit-Signal (im stdio-Modus sofort senden, im Daemon-Modus pro Client bei Connect)
|
||||
|
|
|
|||
|
|
@ -173,7 +173,10 @@ fn start_daemon(script_path: &std::path::Path) -> Result<u32, String> {
|
|||
|
||||
println!("🔌 Starte Bridge-Daemon: {:?} --socket {}", script_path, SOCKET_PATH);
|
||||
|
||||
// --max-old-space-size=4096: Node-Default (~2GB) reicht nicht bei langen Sessions
|
||||
// mit großen Thinking-Blocks/Agent-SDK-History (KB #crash-oom-stacktrace).
|
||||
let child = Command::new("node")
|
||||
.arg("--max-old-space-size=4096")
|
||||
.arg(script_path)
|
||||
.arg("--socket")
|
||||
.arg(SOCKET_PATH)
|
||||
|
|
@ -328,6 +331,7 @@ fn start_bridge_stdio(app: &AppHandle, script_path: &std::path::Path) -> Result<
|
|||
println!("📂 Bridge Arbeitsverzeichnis: {:?}", project_dir);
|
||||
|
||||
let mut child = Command::new("node")
|
||||
.arg("--max-old-space-size=4096")
|
||||
.arg(script_path)
|
||||
.current_dir(project_dir)
|
||||
.stdin(Stdio::piped())
|
||||
|
|
|
|||
Loading…
Reference in a new issue