fix: close child stdin so pnpm PowerShell shim doesn't deadlock on Windows#66
Closed
fix: close child stdin so pnpm PowerShell shim doesn't deadlock on Windows#66
Conversation
Wrap pwsh invocation with timestamped stage markers and a 30s descendant-process heartbeat (via Start-ThreadJob) so a silent hang inside install.ps1 (e.g. pnpm install during `vp install`) is visible in CI logs instead of timing out blind. Driven by hangs on test (windows-latest, alpha) where the job hits 5+ minutes of silence after install.ps1 prints "Setting up VITE+..." and gets canceled.
@actions/exec leaves child stdin open by default. pnpm's pnpm.ps1 shim takes the `$MyInvocation.ExpectingInput` branch when stdin is a pipe and drains $input until EOF before invoking node. With our stdin inherited and never closed, that drain blocks forever — pwsh.exe running pnpm.ps1 stays alive but no node child is ever spawned, and the job times out silently. Pass an empty Buffer as input so the child sees immediate EOF on stdin and the shim falls through to spawn node. Repro: setup-vp@latest with version: alpha on windows-latest hangs 5+ minutes after `Setting up VITE+...`. Heartbeat tracing on the diagnostic commit (reverted in this commit) showed pnpm.ps1 alive without a node descendant.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR modifies the GitHub Action’s Vite+ installer invocation to avoid a Windows-specific hang by explicitly closing stdin for the child process.
Changes:
- Pass
input: Buffer.alloc(0)to@actions/execso the spawnedpwsh(and currently alsobash) process sees EOF on stdin. - Regenerate
dist/index.mjsto include the compiled change.
Reviewed changes
Copilot reviewed 1 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/install-viteplus.ts | Adds exec options to close stdin (empty input) during install to prevent PowerShell/pnpm shim deadlock. |
| dist/index.mjs | Updates the bundled output to reflect the new exec option. |
Comments suppressed due to low confidence (1)
src/install-viteplus.ts:68
input: Buffer.alloc(0)is currently applied to both the Windowspwshpath and the non-Windowsbashpath, but the rationale in the comment is Windows/pnpm-specific. Consider scoping the stdin-closing behavior toprocess.platform === "win32"(or adding a short note explaining why it’s safe/desirable on non-Windows too) to avoid unnecessarily changing install.sh execution semantics.
// Close child stdin (empty input) so pnpm's PowerShell shim doesn't deadlock.
// The shim's `$MyInvocation.ExpectingInput` branch drains $input until EOF
// before invoking node; if we leave stdin open, that drain never returns and
// pnpm install hangs forever — observed on Windows alpha runs with
// vite-plus@0.1.21-alpha.2 (pwsh.exe -File pnpm.ps1 alive, no node child).
const options = { env, ignoreReturnCode: true, input: Buffer.alloc(0) };
if (process.platform === "win32") {
return exec(
"pwsh",
["-Command", `& ([scriptblock]::Create((irm ${INSTALL_URL_PS1})))`],
options,
);
}
return exec("bash", ["-c", `curl -fsSL ${INSTALL_URL_SH} | bash`], options);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+55
to
+60
| // Close child stdin (empty input) so pnpm's PowerShell shim doesn't deadlock. | ||
| // The shim's `$MyInvocation.ExpectingInput` branch drains $input until EOF | ||
| // before invoking node; if we leave stdin open, that drain never returns and | ||
| // pnpm install hangs forever — observed on Windows alpha runs with | ||
| // vite-plus@0.1.21-alpha.2 (pwsh.exe -File pnpm.ps1 alive, no node child). | ||
| const options = { env, ignoreReturnCode: true, input: Buffer.alloc(0) }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
@actions/execleaves child stdin open by default. pnpm'spnpm.ps1shim takes the$MyInvocation.ExpectingInputbranch when stdin is a pipe and drains$inputuntil EOF before invokingnode. With stdin inherited from the runner and never closed, that drain blocks forever —pwsh.exerunningpnpm.ps1stays alive but nonodechild is ever spawned, and the job times out silently.Fix: pass
input: Buffer.alloc(0)toexecso the child sees immediate EOF on stdin and the shim falls through to spawnnode.Repro & evidence
Failing run before fix: https://github.com/voidzero-dev/setup-vp/actions/runs/24870325083/job/74809705560 —
test (windows-latest, alpha)hangs 5+ minutes afterSetting up VITE+...then is canceled.windows-latest, latestfinishes in ~13s on the same install path.A short-lived diagnostic commit (replaced by this fix) added a heartbeat that snapshotted descendants of the pwsh PID every 30s. It showed:
Same tree across three consecutive heartbeats, never spawning a node child — the pnpm shim is alive but blocked on draining stdin before it ever invokes node.
Test plan
test (windows-latest, alpha)runs to completion on this PR (previously hung).curl | bashpipe is independent of the outer bash's stdin).vp testpasses (115/115).