diff --git a/packages/cli/package.json b/packages/cli/package.json index 0e945949..1e1a1ef3 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@openrouter/spawn", - "version": "0.10.12", + "version": "0.10.13", "type": "module", "bin": { "spawn": "cli.js" diff --git a/packages/cli/src/aws/aws.ts b/packages/cli/src/aws/aws.ts index a984105f..d5a54788 100644 --- a/packages/cli/src/aws/aws.ts +++ b/packages/cli/src/aws/aws.ts @@ -977,17 +977,23 @@ export async function waitForCloudInit(maxAttempts = 60): Promise { ...SSH_BASE_OPTS, ...keyOpts, `${SSH_USER}@${instanceIp}`, - "test -f /home/ubuntu/.cloud-init-complete", + "test -f /home/ubuntu/.cloud-init-complete && echo done", ], { stdio: [ "ignore", "pipe", - "ignore", + "pipe", ], }, ); - if ((await proc.exited) === 0) { + // Drain both pipes before awaiting exit to prevent pipe buffer deadlock + const [stdout] = await Promise.all([ + new Response(proc.stdout).text(), + new Response(proc.stderr).text(), + ]); + const exitCode = await proc.exited; + if (exitCode === 0 && stdout.includes("done")) { logInfo("Cloud-init complete"); return; } diff --git a/packages/cli/src/sprite/sprite.ts b/packages/cli/src/sprite/sprite.ts index e2584ee0..3b7962d7 100644 --- a/packages/cli/src/sprite/sprite.ts +++ b/packages/cli/src/sprite/sprite.ts @@ -634,11 +634,13 @@ export async function destroyServer(name?: string): Promise { ], }, ); + // Drain stderr before awaiting exit to prevent pipe buffer deadlock + const stderrText = new Response(proc.stderr).text(); const exitCode = await proc.exited; if (exitCode !== 0) { logError(`Failed to destroy sprite '${target}'`); logError(`Delete it manually: sprite destroy ${target}`); - throw new Error("Sprite destruction failed"); + throw new Error(`Sprite destruction failed: ${await stderrText}`); } logInfo(`Sprite '${target}' destroyed`);