fix: auto-terminate stale bot instances to prevent port conflicts

- Added execSync import for child_process
- Modified acquirePidfile() to send SIGTERM to old instances
- Waits up to 2.5s for graceful shutdown with checks every 500ms
- Prevents continuous restart loop when old PID holds port 3001
- Bot now self-heals on restart instead of crashing
This commit is contained in:
admin
2026-05-06 10:32:30 +00:00
Unverified
parent d51ab51032
commit c164446a9c

View File

@@ -6,6 +6,7 @@ import { createServer } from 'http';
import { WebSocketServer } from 'ws';
import fs from 'fs';
import path from 'path';
import { execSync } from 'child_process';
import { logger } from '../utils/logger.js';
import { checkEnv } from '../utils/env.js';
import { getRTK } from '../utils/rtk.js';
@@ -37,16 +38,33 @@ function acquirePidfile() {
if (fs.existsSync(PIDFILE)) {
const oldPid = parseInt(fs.readFileSync(PIDFILE, 'utf8').trim());
// Check if old process is still alive
try { process.kill(oldPid, 0);
// Same PID or different process - just log warning, don't kill
try { process.kill(oldPid, 0);
// Old process is still running - kill it to prevent port conflicts
if (oldPid !== process.pid) {
logger.warn(`⚠ Another zCode instance (PID ${oldPid}) is running — keeping this instance (PID ${process.pid})`);
logger.warn(`⚠ Another zCode instance (PID ${oldPid}) detected — terminating to prevent port conflict`);
try {
process.kill(oldPid, 'SIGTERM');
logger.info(` ✓ Sent SIGTERM to PID ${oldPid}`);
// Give it time to shut down gracefully
for (let i = 0; i < 5; i++) {
try { process.kill(oldPid, 0); }
catch { break; } // Process is dead
if (i < 4) {
// Sleep 500ms between checks
execSync('sleep 0.5', { stdio: 'ignore' });
}
}
} catch (e) {
logger.warn(` Failed to kill old PID ${oldPid}: ${e.message}`);
}
} else {
logger.info(`✓ Pidfile already acquired by this instance (PID ${process.pid})`);
}
// Don't kill - just continue with current process
return;
} catch { /* old PID dead, safe to acquire */ }
// Continue - old process should be dead now
} catch {
// Old PID dead, safe to acquire
logger.info(` Old PID ${oldPid} is no longer running`);
}
}
fs.writeFileSync(PIDFILE, process.pid.toString());
logger.info(`✓ Pidfile acquired: ${PIDFILE} (PID ${process.pid})`);