mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-15 23:56:29 +03:00
fix: probe the recorded port for live-server liveness
greptile-apps[bot] re-raised the residual with a repro: a stale server.json pid reused by an unrelated node process passed the command-name check. The decisive signal is the recorded PORT: a real helper is listening on it, a pid squatter is not. hasLiveServer now probes 127.0.0.1:<port> (bash /dev/tcp, sync, ~ms, win32-guarded with the previous behavior); the multi-app preference test runs a real listener instead of faking liveness with a bare pid. This work was produced with AI assistance (Claude Code). Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Code
parent
26f54d15c2
commit
7fa25da98e
@@ -296,19 +296,33 @@ function readPointerEntries(repoRoot) {
|
||||
*/
|
||||
function hasLiveServer(appRoot) {
|
||||
let pid;
|
||||
let port;
|
||||
try {
|
||||
const info = JSON.parse(fs.readFileSync(path.join(appRoot, '.impeccable', 'live', 'server.json'), 'utf-8'));
|
||||
if (!info || typeof info.pid !== 'number') return false;
|
||||
pid = info.pid;
|
||||
port = Number(info.port);
|
||||
process.kill(pid, 0);
|
||||
} catch (err) {
|
||||
// EPERM: the process exists but is not signalable by this user.
|
||||
if (err?.code !== 'EPERM') return false;
|
||||
}
|
||||
if (process.platform === 'win32') return true; // no cheap portable command check
|
||||
// Liveness alone misclassifies a REUSED pid (helper died without removing
|
||||
// server.json, the OS handed the pid to something else, even another node
|
||||
// process). The decisive signal is the recorded PORT: a real helper is
|
||||
// listening on it, a pid squatter is not.
|
||||
if (Number.isInteger(port) && port > 0 && process.platform !== 'win32') {
|
||||
try {
|
||||
execFileSync('bash', ['-c', `exec 3<>/dev/tcp/127.0.0.1/${port}`], { timeout: 1500, stdio: 'ignore' });
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (process.platform === 'win32') return true; // no cheap portable probe
|
||||
try {
|
||||
const command = execFileSync('ps', ['-p', String(pid), '-o', 'command='], { encoding: 'utf-8' });
|
||||
return /\b(node|bun|live-server)\b/.test(command);
|
||||
return /live-server|\b(node|bun)\b/.test(command);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user