mirror of https://github.com/garrytan/gstack.git
fix: crash handling — save session, kill agent, distinct exit codes
Hardened shutdown/crash behavior: - Browser disconnect exits with code 2 (distinct from crash code 1) - emergencyCleanup kills agent subprocess and saves session state - Clean shutdown saves session before exit (chat history persists) - Clear user message on browser disconnect: "Run $B connect to reconnect" Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
530a4ef22c
commit
cf8416290d
|
|
@ -242,12 +242,13 @@ export class BrowserManager {
|
||||||
await this.newTab();
|
await this.newTab();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Browser disconnect handler
|
// Browser disconnect handler — exit code 2 distinguishes from crashes (1)
|
||||||
if (this.browser) {
|
if (this.browser) {
|
||||||
this.browser.on('disconnected', () => {
|
this.browser.on('disconnected', () => {
|
||||||
if (this.intentionalDisconnect) return;
|
if (this.intentionalDisconnect) return;
|
||||||
console.error('[browse] Real browser disconnected.');
|
console.error('[browse] Real browser disconnected (user closed or crashed).');
|
||||||
process.exit(1);
|
console.error('[browse] Run `$B connect` to reconnect.');
|
||||||
|
process.exit(2);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -601,6 +601,7 @@ async function shutdown() {
|
||||||
console.log('[browse] Shutting down...');
|
console.log('[browse] Shutting down...');
|
||||||
killAgent();
|
killAgent();
|
||||||
messageQueue = [];
|
messageQueue = [];
|
||||||
|
saveSession(); // Persist chat history before exit
|
||||||
if (agentHealthInterval) clearInterval(agentHealthInterval);
|
if (agentHealthInterval) clearInterval(agentHealthInterval);
|
||||||
clearInterval(flushInterval);
|
clearInterval(flushInterval);
|
||||||
clearInterval(idleCheckInterval);
|
clearInterval(idleCheckInterval);
|
||||||
|
|
@ -624,10 +625,15 @@ async function shutdown() {
|
||||||
process.on('SIGTERM', shutdown);
|
process.on('SIGTERM', shutdown);
|
||||||
process.on('SIGINT', shutdown);
|
process.on('SIGINT', shutdown);
|
||||||
|
|
||||||
// Emergency cleanup for crashes (OOM, uncaught exceptions)
|
// Emergency cleanup for crashes (OOM, uncaught exceptions, browser disconnect)
|
||||||
function emergencyCleanup() {
|
function emergencyCleanup() {
|
||||||
if (isShuttingDown) return;
|
if (isShuttingDown) return;
|
||||||
isShuttingDown = true;
|
isShuttingDown = true;
|
||||||
|
// Kill agent subprocess if running
|
||||||
|
try { killAgent(); } catch {}
|
||||||
|
// Save session state so chat history persists across crashes
|
||||||
|
try { saveSession(); } catch {}
|
||||||
|
// Clean Chromium profile locks
|
||||||
const profileDir = path.join(process.env.HOME || '/tmp', '.gstack', 'chromium-profile');
|
const profileDir = path.join(process.env.HOME || '/tmp', '.gstack', 'chromium-profile');
|
||||||
for (const lockFile of ['SingletonLock', 'SingletonSocket', 'SingletonCookie']) {
|
for (const lockFile of ['SingletonLock', 'SingletonSocket', 'SingletonCookie']) {
|
||||||
try { fs.unlinkSync(path.join(profileDir, lockFile)); } catch {}
|
try { fs.unlinkSync(path.join(profileDir, lockFile)); } catch {}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue