mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-02 22:17:14 +00:00
fix(docker): wrap session registration in try-catch and narrow ETXTBSY guard
Session registration in spawn handler can throw on lock contention or disk errors — wrap in try-catch to prevent silent proxy-untracked state. Narrow EBUSY catch to ETXTBSY only since EBUSY on non-Linux platforms can mean mount point or directory in use, not running binary. Fix misleading "skip" comment to say "abort".
This commit is contained in:
@@ -36,8 +36,8 @@ export async function downloadAndInstall(
|
|||||||
fs.mkdirSync(config.binPath, { recursive: true });
|
fs.mkdirSync(config.binPath, { recursive: true });
|
||||||
|
|
||||||
// Delete existing binary before install to prevent mismatched binaries.
|
// Delete existing binary before install to prevent mismatched binaries.
|
||||||
// Skip if binary is currently running (ETXTBSY) — happens in Docker when
|
// Abort if binary is currently running (ETXTBSY) — cannot replace in-use binary.
|
||||||
// the dashboard tries to update while bootstrap's instance is active.
|
// Happens in Docker when dashboard tries to update while bootstrap's instance is active.
|
||||||
const existingBinary = path.join(config.binPath, getExecutableName(backend));
|
const existingBinary = path.join(config.binPath, getExecutableName(backend));
|
||||||
if (fs.existsSync(existingBinary)) {
|
if (fs.existsSync(existingBinary)) {
|
||||||
try {
|
try {
|
||||||
@@ -46,9 +46,12 @@ export async function downloadAndInstall(
|
|||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const code =
|
const code =
|
||||||
error instanceof Error && 'code' in error ? (error as { code: string }).code : '';
|
error instanceof Error && 'code' in error ? (error as { code: string }).code : '';
|
||||||
if (code === 'ETXTBSY' || code === 'EBUSY') {
|
// ETXTBSY: Linux-specific error when unlinking a running executable.
|
||||||
|
// EBUSY on Windows may mean something different (mount point, etc.),
|
||||||
|
// so only treat ETXTBSY as "binary in use" to avoid misleading messages.
|
||||||
|
if (code === 'ETXTBSY') {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
console.error(`[cliproxy] Binary is running, skipping update: ${existingBinary}`);
|
console.error(`[cliproxy] Binary is running, cannot replace: ${existingBinary}`);
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'CLIProxy binary is currently running and cannot be replaced. Restart the container to apply the update.'
|
'CLIProxy binary is currently running and cannot be replaced. Restart the container to apply the update.'
|
||||||
);
|
);
|
||||||
@@ -120,7 +123,7 @@ export function deleteBinary(binPath: string, verbose = false, backend?: CLIProx
|
|||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const code =
|
const code =
|
||||||
error instanceof Error && 'code' in error ? (error as { code: string }).code : '';
|
error instanceof Error && 'code' in error ? (error as { code: string }).code : '';
|
||||||
if (code === 'ETXTBSY' || code === 'EBUSY') {
|
if (code === 'ETXTBSY') {
|
||||||
throw new Error('CLIProxy binary is currently running and cannot be deleted.');
|
throw new Error('CLIProxy binary is currently running and cannot be deleted.');
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@@ -38,8 +38,14 @@ async function runCliproxy(): Promise<number> {
|
|||||||
let sessionId: string | undefined;
|
let sessionId: string | undefined;
|
||||||
child.on('spawn', () => {
|
child.on('spawn', () => {
|
||||||
if (!child.pid) return;
|
if (!child.pid) return;
|
||||||
const version = getInstalledCliproxyVersion();
|
try {
|
||||||
sessionId = registerSession(CLIPROXY_DEFAULT_PORT, child.pid, version, 'plus');
|
const version = getInstalledCliproxyVersion();
|
||||||
|
sessionId = registerSession(CLIPROXY_DEFAULT_PORT, child.pid, version, 'plus');
|
||||||
|
} catch (err) {
|
||||||
|
console.error(
|
||||||
|
`[cliproxy] Failed to register session lock: ${err instanceof Error ? err.message : String(err)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
child.on('error', reject);
|
child.on('error', reject);
|
||||||
|
|||||||
Reference in New Issue
Block a user