diff --git a/packages/cli/src/aws/aws.ts b/packages/cli/src/aws/aws.ts index c4888fd0..55febd71 100644 --- a/packages/cli/src/aws/aws.ts +++ b/packages/cli/src/aws/aws.ts @@ -1062,7 +1062,11 @@ export async function runServerCapture(cmd: string, timeoutSecs?: number): Promi /* ignore */ } }, timeout); - const stdout = await new Response(proc.stdout).text(); + // 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; clearTimeout(timer); if (exitCode !== 0) { diff --git a/packages/cli/src/digitalocean/digitalocean.ts b/packages/cli/src/digitalocean/digitalocean.ts index 938207b9..fd2f11ba 100644 --- a/packages/cli/src/digitalocean/digitalocean.ts +++ b/packages/cli/src/digitalocean/digitalocean.ts @@ -928,7 +928,11 @@ export async function waitForCloudInit(ip?: string, _maxAttempts = 60): Promise< ], }, ); - const stdout = await new Response(proc.stdout).text(); + // 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(), + ]); if ((await proc.exited) === 0 && stdout.includes("done")) { logInfo("Cloud-init complete"); return; @@ -1011,7 +1015,11 @@ export async function runServerCapture(cmd: string, timeoutSecs?: number, ip?: s proc.kill(); } catch {} }, timeout); - const stdout = await new Response(proc.stdout).text(); + // 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; try { proc.stdin!.end(); diff --git a/packages/cli/src/gcp/gcp.ts b/packages/cli/src/gcp/gcp.ts index 92075a9d..522a702d 100644 --- a/packages/cli/src/gcp/gcp.ts +++ b/packages/cli/src/gcp/gcp.ts @@ -792,6 +792,11 @@ export async function waitForCloudInit(maxAttempts = 60): Promise { ], }, ); + // Drain both pipes before awaiting exit to prevent pipe buffer deadlock + await Promise.all([ + new Response(proc.stdout).text(), + new Response(proc.stderr).text(), + ]); if ((await proc.exited) === 0) { logInfo("Startup script completed"); return; @@ -868,7 +873,11 @@ export async function runServerCapture(cmd: string, timeoutSecs?: number): Promi proc.kill(); } catch {} }, timeout); - const stdout = await new Response(proc.stdout).text(); + // 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; clearTimeout(timer); if (exitCode !== 0) { diff --git a/packages/cli/src/hetzner/hetzner.ts b/packages/cli/src/hetzner/hetzner.ts index c4a8949e..fcb4cfd9 100644 --- a/packages/cli/src/hetzner/hetzner.ts +++ b/packages/cli/src/hetzner/hetzner.ts @@ -489,7 +489,11 @@ export async function waitForCloudInit(ip?: string, _maxAttempts = 60): Promise< ], }, ); - const stdout = await new Response(proc.stdout).text(); + // 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"); @@ -576,7 +580,11 @@ export async function runServerCapture(cmd: string, timeoutSecs?: number, ip?: s proc.kill(); } catch {} }, timeout); - const stdout = await new Response(proc.stdout).text(); + // 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; try { proc.stdin!.end();