mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 10:16:49 +00:00
fix(docker): address review findings — PID guard, deleteBinary guard, blocked fallback
- Guard child.pid falsy in bootstrap (PID 0 creates immortal phantom lock) - Add ETXTBSY/EBUSY guard to deleteBinary() (same vuln as downloadAndInstall) - Fix error message to suggest container restart (not circular ccs docker update) - Tighten status.blocked guard to handle missing blocker gracefully
This commit is contained in:
@@ -50,7 +50,7 @@ export async function downloadAndInstall(
|
||||
if (verbose)
|
||||
console.error(`[cliproxy] Binary is running, skipping update: ${existingBinary}`);
|
||||
throw new Error(
|
||||
`CLIProxy binary is currently running and cannot be replaced. Stop the running instance first, or use 'ccs docker update' to update in place.`
|
||||
'CLIProxy binary is currently running and cannot be replaced. Restart the container to apply the update.'
|
||||
);
|
||||
}
|
||||
throw error;
|
||||
@@ -114,8 +114,17 @@ export function deleteBinary(binPath: string, verbose = false, backend?: CLIProx
|
||||
const effectiveBackend = backend ?? DEFAULT_BACKEND;
|
||||
const binaryPath = path.join(binPath, getExecutableName(effectiveBackend));
|
||||
if (fs.existsSync(binaryPath)) {
|
||||
fs.unlinkSync(binaryPath);
|
||||
if (verbose) console.error(`[cliproxy] Deleted: ${binaryPath}`);
|
||||
try {
|
||||
fs.unlinkSync(binaryPath);
|
||||
if (verbose) console.error(`[cliproxy] Deleted: ${binaryPath}`);
|
||||
} catch (error: unknown) {
|
||||
const code =
|
||||
error instanceof Error && 'code' in error ? (error as { code: string }).code : '';
|
||||
if (code === 'ETXTBSY' || code === 'EBUSY') {
|
||||
throw new Error('CLIProxy binary is currently running and cannot be deleted.');
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,8 +37,9 @@ async function runCliproxy(): Promise<number> {
|
||||
// Register session lock so dashboard can detect the running proxy
|
||||
let sessionId: string | undefined;
|
||||
child.on('spawn', () => {
|
||||
const version = getInstalledCliproxyVersion() ?? undefined;
|
||||
sessionId = registerSession(CLIPROXY_DEFAULT_PORT, child.pid ?? 0, version, 'plus');
|
||||
if (!child.pid) return;
|
||||
const version = getInstalledCliproxyVersion();
|
||||
sessionId = registerSession(CLIPROXY_DEFAULT_PORT, child.pid, version, 'plus');
|
||||
});
|
||||
|
||||
child.on('error', reject);
|
||||
|
||||
@@ -158,14 +158,16 @@ export async function checkCliproxyPort(): Promise<HealthCheck> {
|
||||
};
|
||||
}
|
||||
|
||||
if (status.blocked && status.blocker) {
|
||||
if (status.blocked) {
|
||||
return {
|
||||
id: 'cliproxy-port',
|
||||
name: 'CLIProxy Port',
|
||||
status: 'warning',
|
||||
message: `Occupied by ${status.blocker.processName}`,
|
||||
details: `PID ${status.blocker.pid}`,
|
||||
fix: `Kill process: kill ${status.blocker.pid}`,
|
||||
message: status.blocker
|
||||
? `Occupied by ${status.blocker.processName}`
|
||||
: 'Port occupied by unknown process',
|
||||
details: status.blocker ? `PID ${status.blocker.pid}` : undefined,
|
||||
...(status.blocker && { fix: `Kill process: kill ${status.blocker.pid}` }),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user