From 2907ff60682ae75068619621c932b103a83cbfe2 Mon Sep 17 00:00:00 2001 From: A <258483684+la14-1@users.noreply.github.com> Date: Wed, 25 Feb 2026 06:26:27 -0800 Subject: [PATCH] fix: drain piped stderr in CLI installers and uploadFile to prevent deadlock (#1922) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #1920 fixed pipe buffer deadlock in runServerCapture and waitForCloudInit but missed 6 other locations where Bun.spawn uses "pipe" for stderr without draining it before await proc.exited. When a child process writes >64KB to a piped stderr, the OS pipe buffer fills, the child blocks on write(), and the parent blocks on exited — classic deadlock. Fix: change stderr from "pipe" to "inherit" in all 6 locations since the stderr output is never read programmatically. This also lets users see installation errors and SCP errors in real time. Affected functions: - fly.ts ensureFlyCli() - sprite.ts ensureSpriteCli() - gcp.ts ensureGcloudCli() - hetzner.ts uploadFile() - digitalocean.ts uploadFile() - aws.ts uploadFile() -- refactor/code-health Agent: code-health Co-authored-by: B <6723574+louisgv@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.5 --- packages/cli/package.json | 2 +- packages/cli/src/aws/aws.ts | 4 ++-- packages/cli/src/digitalocean/digitalocean.ts | 4 ++-- packages/cli/src/fly/fly.ts | 4 ++-- packages/cli/src/gcp/gcp.ts | 2 +- packages/cli/src/hetzner/hetzner.ts | 4 ++-- packages/cli/src/sprite/sprite.ts | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 8fea475d..f32200c7 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@openrouter/spawn", - "version": "0.10.10", + "version": "0.10.11", "type": "module", "bin": { "spawn": "cli.js" diff --git a/packages/cli/src/aws/aws.ts b/packages/cli/src/aws/aws.ts index 55febd71..a984105f 100644 --- a/packages/cli/src/aws/aws.ts +++ b/packages/cli/src/aws/aws.ts @@ -1091,8 +1091,8 @@ export async function uploadFile(localPath: string, remotePath: string): Promise { stdio: [ "ignore", - "ignore", - "pipe", + "inherit", + "inherit", ], }, ); diff --git a/packages/cli/src/digitalocean/digitalocean.ts b/packages/cli/src/digitalocean/digitalocean.ts index fd2f11ba..2c8a7a48 100644 --- a/packages/cli/src/digitalocean/digitalocean.ts +++ b/packages/cli/src/digitalocean/digitalocean.ts @@ -1053,8 +1053,8 @@ export async function uploadFile(localPath: string, remotePath: string, ip?: str { stdio: [ "ignore", - "ignore", - "pipe", + "inherit", + "inherit", ], }, ); diff --git a/packages/cli/src/fly/fly.ts b/packages/cli/src/fly/fly.ts index 277e03d0..6d152b7e 100644 --- a/packages/cli/src/fly/fly.ts +++ b/packages/cli/src/fly/fly.ts @@ -325,8 +325,8 @@ export async function ensureFlyCli(): Promise { { stdio: [ "ignore", - "ignore", - "pipe", + "inherit", + "inherit", ], }, ); diff --git a/packages/cli/src/gcp/gcp.ts b/packages/cli/src/gcp/gcp.ts index 522a702d..1cbd9652 100644 --- a/packages/cli/src/gcp/gcp.ts +++ b/packages/cli/src/gcp/gcp.ts @@ -352,7 +352,7 @@ export async function ensureGcloudCli(): Promise { stdio: [ "ignore", "inherit", - "pipe", + "inherit", ], }, ); diff --git a/packages/cli/src/hetzner/hetzner.ts b/packages/cli/src/hetzner/hetzner.ts index fcb4cfd9..e9306cc3 100644 --- a/packages/cli/src/hetzner/hetzner.ts +++ b/packages/cli/src/hetzner/hetzner.ts @@ -619,8 +619,8 @@ export async function uploadFile(localPath: string, remotePath: string, ip?: str { stdio: [ "ignore", - "ignore", - "pipe", + "inherit", + "inherit", ], }, ); diff --git a/packages/cli/src/sprite/sprite.ts b/packages/cli/src/sprite/sprite.ts index 81ce5a55..e2584ee0 100644 --- a/packages/cli/src/sprite/sprite.ts +++ b/packages/cli/src/sprite/sprite.ts @@ -153,7 +153,7 @@ export async function ensureSpriteCli(): Promise { stdio: [ "ignore", "inherit", - "pipe", + "inherit", ], }, );