Skip to content

Preserve signal zero with descendant termination - #1

Draft
teamleaderleo wants to merge 4 commits into
mainfrom
fieldwork/kill-descendants-signal-zero
Draft

Preserve signal zero with descendant termination#1
teamleaderleo wants to merge 4 commits into
mainfrom
fieldwork/kill-descendants-signal-zero

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Jul 29, 2026

Copy link
Copy Markdown
Owner

In simple words

Execa supports subprocess.kill(0) as a non-destructive process-existence check. With killDescendants: true, the Windows implementation routes termination through forced taskkill /T /F, which previously could turn that liveness check into process-tree termination.

This draft handles signal 0 before selecting any platform-specific descendant-termination adapter. Non-zero signals continue to terminate the process tree.

Changes

  • preserve signal 0 through the native child-process liveness check on every platform;
  • add a deterministic Windows-adapter regression proving taskkill is not called;
  • add a live process-tree regression proving the child and descendant remain alive after kill(0);
  • add a delayed-escalation regression proving forceKillAfterDelay does not later terminate the tree;
  • retain the existing assertion that a normal kill terminates the tree.

Self-review correction

The first revision handled signal 0 only inside the Windows adapter. Review moved the guard into the shared dispatcher so the contract is explicit and platform-independent: killDescendants changes termination behavior, not liveness-check semantics.

Validation

Fieldwork workflow 30491600304 checked out this exact branch and ran the focused repository tests on:

  • Node 22, 24, and 26 on Ubuntu;
  • Node 22, 24, and 26 on Windows.

All six jobs passed. The Windows jobs used a real hosted Windows runner and the real taskkill.exe path.

Additional local source execution on Node 22.16.0 confirmed:

  • signal 0 called the native child check and launched no taskkill;
  • a later SIGTERM launched the expected /T /F command;
  • a real Unix process group preserved parent and grandchild after signal 0, then terminated both for a normal signal.

Prior-art check

No matching current Execa issue or pull request was found. The closest precedent is merged PR sindresorhus#1258, which deliberately routes Windows descendant termination through taskkill and falls back to the requested signal only when taskkill is unavailable or fails. That path did not special-case the non-terminating signal 0.

Research boundary

This is owned-fork Fieldwork research. It is not intended for upstream submission without separate authorization.

Copy link
Copy Markdown
Owner Author

Exact-head review — dc73ffcd1765666f77fb39775af73abec08c5bb5

Disposition: ACCEPT as a target-executed owned-fork implementation candidate; HOLD upstream promotion.

The shared-dispatch guard is the right boundary. Signal 0 is a liveness query, not a termination request, so it should bypass both Unix process-group signaling and Windows taskkill /T /F. Non-zero descendant termination remains unchanged.

The current diff has useful independent controls:

  • deterministic Windows adapter check proving taskkill is not invoked;
  • live process-tree check proving parent and descendant remain alive;
  • delayed-force-kill control proving no later escalation is scheduled;
  • normal non-zero kill still terminates the tree;
  • focused Ubuntu and hosted-Windows execution across Node 22/24/26 is retained in the PR description.

Review limitations before any submission decision:

  1. There is no repository-native workflow receipt on this exact head; the retained evidence is a Fieldwork workflow checking out the branch. Keep that evidence class as target-executed, not full-gate.
  2. Run the ordinary Execa repository gate on the exact candidate head, including lint/types/tests outside the focused files.
  3. Recheck the documented/API contract for subprocess.kill(0) and killDescendants so the PR explains that the new check is intentionally direct-child liveness, not process-group membership.
  4. Preserve the current small source diff; do not add platform-specific special cases back into the adapters.

No correctness defect found in the reviewed source change. Any head movement expires this disposition. No upstream contact.

@teamleaderleo teamleaderleo left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exact-head review — dc73ffcd1765666f77fb39775af73abec08c5bb5

Disposition: ACCEPT the owned-fork implementation candidate; HOLD upstream promotion pending a separate authorization decision.

Evidence class: target-executed for the focused six-job Ubuntu/Windows matrix. This is not a full repository gate.

The complete three-file diff is appropriately narrow:

  • signal 0 is handled in the shared descendant-kill dispatcher before either platform adapter is selected;
  • the native ChildProcess.kill(0) liveness contract remains authoritative;
  • all non-zero signals retain the existing Unix process-group or Windows taskkill /T /F path;
  • the live process-tree test proves the direct child and descendant remain alive after signal 0 and still terminate under a normal kill;
  • the delayed-force-kill test proves forceKillAfterDelay does not convert the liveness check into later termination;
  • the Windows adapter control proves taskkill is not invoked for signal 0.

I found no missing error-preservation, adapter-selection, or cleanup blocker in this scope. The central guard is better than the earlier Windows-only version because killDescendants should alter termination delivery, not redefine signal-zero semantics by platform.

Remaining boundary:

  • retain the exact focused matrix receipt and avoid calling it full-gate;
  • refresh duplicate/prior-art search at the then-current upstream head before any packet is prepared;
  • keep upstream contact unauthorized until a specific submission is reviewed.

No additional implementation work is required for the stated candidate.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant