Skip to content

[rush] rushd: cancelling rushx-client (Ctrl+C/SIGTERM) SIGKILLs the script without a graceful signal and exits 1 with "An unknown error occurred." #6074

Description

Summary

rushx-client forwards SIGINT/SIGTERM as requestCancel. The daemon then aborts the GlobalCommandExecutionContext, whose terminateChild immediately calls SubprocessTerminator.killProcessTree, which is process.kill(-pid, 'SIGKILL'). The script never receives SIGINT or SIGTERM. Dev servers leave lock/pid files and ports behind, and test runners skip teardown. RushXCommand then reports the killed shell as Error: An unknown error occurred., and the client exits 1 instead of 130/143.

Repro steps

Take a rushx script that traps SIGINT/SIGTERM/SIGHUP, writes a marker file, and exits 40.

action rushx-client (daemon) native rushx
SIGINT to the client exit 1, child SIGKILLed, trap not run, prints "Error: An unknown error occurred." terminal Ctrl+C: trap runs, exit 130
SIGTERM to the client exit 1, trap not run, same message exit 143

To its credit, the daemon kills the whole tree, so no orphans are left behind.

Expected result: Emulate a terminal Ctrl+C. Send the same signal (SIGINT/SIGTERM) to the script's process group, wait a bounded grace period (for example 2-5 s, within the client's cancellation timeout), then SIGKILL. The client exits 128 + signo and does not print a bogus "unknown error".

Actual result: The script is killed immediately with SIGKILL, the client exits 1, and the message is misleading.

Details

Root cause (main @ 60007c9): libraries/rush-daemon/src/GlobalCommandExecutionContext.ts:343-355 (terminateChild) calls killProcessTree (SIGKILL) directly. CommandResultPolicy.ts:65-68 maps the result to exit code 1.

Suggested fix: add a graceful phase: process.kill(-child.pid, requestSignal ?? 'SIGINT'), then killProcessTree after a grace timeout. Carry the client's signal in requestCancel (for example an additive optional signal field). Suppress the "unknown error" message for aborted requests, and return 130/143 (related: #6060, for phased builds).

This was found during an automated performance/behavior analysis of rush-client/rushd on Linux and independently reproduced.

Standard questions

Question Answer
@microsoft/rush globally installed version? built from main @ 60007c9 (5.179.0)
rushVersion from rush.json? 5.179.0
pnpmVersion, npmVersion, or yarnVersion from rush.json? pnpm@10.27.0
(if pnpm) useWorkspaces from pnpm-config.json? true
Operating system? Linux (WSL2 Ubuntu 24.04)
Would you consider contributing a PR? Yes
Node.js version (node -v)? 22.23.2

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    • Status
      Needs triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions