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:
@@ -6,6 +6,7 @@ import { createServer } from 'http';
|
|||||||
import { WebSocketServer } from 'ws';
|
import { WebSocketServer } from 'ws';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import { execSync } from 'child_process';
|
||||||
import { logger } from '../utils/logger.js';
|
import { logger } from '../utils/logger.js';
|
||||||
import { checkEnv } from '../utils/env.js';
|
import { checkEnv } from '../utils/env.js';
|
||||||
import { getRTK } from '../utils/rtk.js';
|
import { getRTK } from '../utils/rtk.js';
|
||||||
@@ -38,15 +39,32 @@ function acquirePidfile() {
|
|||||||
const oldPid = parseInt(fs.readFileSync(PIDFILE, 'utf8').trim());
|
const oldPid = parseInt(fs.readFileSync(PIDFILE, 'utf8').trim());
|
||||||
// Check if old process is still alive
|
// Check if old process is still alive
|
||||||
try { process.kill(oldPid, 0);
|
try { process.kill(oldPid, 0);
|
||||||
// Same PID or different process - just log warning, don't kill
|
// Old process is still running - kill it to prevent port conflicts
|
||||||
if (oldPid !== process.pid) {
|
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 {
|
} else {
|
||||||
logger.info(`✓ Pidfile already acquired by this instance (PID ${process.pid})`);
|
logger.info(`✓ Pidfile already acquired by this instance (PID ${process.pid})`);
|
||||||
}
|
}
|
||||||
// Don't kill - just continue with current process
|
// Continue - old process should be dead now
|
||||||
return;
|
} catch {
|
||||||
} catch { /* old PID dead, safe to acquire */ }
|
// Old PID dead, safe to acquire
|
||||||
|
logger.info(` Old PID ${oldPid} is no longer running`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fs.writeFileSync(PIDFILE, process.pid.toString());
|
fs.writeFileSync(PIDFILE, process.pid.toString());
|
||||||
logger.info(`✓ Pidfile acquired: ${PIDFILE} (PID ${process.pid})`);
|
logger.info(`✓ Pidfile acquired: ${PIDFILE} (PID ${process.pid})`);
|
||||||
|
|||||||
Reference in New Issue
Block a user