HarperFast / HarperFast/harper

Use a Windows Job Object for spawned process-tree lifetime instead of reconstructing identity from Win32_Process creation times

Open
#2,599 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
89
Forks
10
Avg merge
2d 6h
Merged PRs (30d)
200

Description

`server/threads/windowsProcessTree.ts` identifies a spawned process tree by reconstructing it from `Win32_Process` creation times: the root by `(PID, creation time)` bounded by the interval measured around `spawn()`, descendants by parentage plus their own creation times, with a 50 ms allowance on the one cross-clock bound. That is ~360 lines of bounds reasoning standing in for an identity the OS can give us directly.

A **Job Object** assigned at process creation and retained by handle makes the tree an OS-level set: `TerminateJobObject` kills exactly the members, and PID reuse stops being part of the problem at all.

### What it would close

Each of these is individually bounded by a heuristic today, and each was found only after the previous one was fixed — which is the argument for replacing the mechanism rather than adding another bound:

- **Ancestry lost before the first snapshot.** A grandchild whose linking ancestors all exited before the first scan cannot be reached by parentage scanning. No heuristic closes this one; it is why the Job Object has been the standing alternative since round 7 of #2470.
- **Scan-to-kill PID reuse.** A member selected by `(PID, creation time)` can exit and have its PID recycled between the scan and the `taskkill`, which names PIDs only.
- **A root PID held by a process with no `CreationDate`.** WMI reports none for some protected processes, so the root's identity never resolves and the confirmation never returns.
- **Recycled process-group ids across threads.** Fixed in #2470 by stamping each group with its owner, but the fix took three rounds — ownership on clear, then ownership on the *stamp* rather than membership, then ownership before the kill and not only before the wait. It also left a trade: filtering a recycled id out of the old owner's sweep abandons that owner's wait for it, where harper#2076's recorded policy prefers a wedged deployment over releasing on an unconfirmed tree. A Job Object dissolves the trade instead of choosing a side.

### Cost

A native dependency (native code or `ffi`), which needs `dependencies.md` justification and review. It also obsoletes `windowsProcessTree.ts` rather than extending it, so it is a replacement, not an increment.

### Related

- harper#2076 — the deadline-free confirmation wait. The Job Object makes the wait unnecessary rather than bounding it.
- harper#2273 — the unrelated-process kill this module exists to prevent; every item above is a path back to it.

### Provenance

Named as the better framing for the Windows half by the `--mode plan` recheck on [Stop a recycled Windows PID from wedging deploy_component and release dropped databases on every thread](https://github.com/HarperFast/harper/pull/2470), twice. @kriszyp ruled it into its own issue rather than into that PR.

Contributor guide

Open the contributing guide

Research direction

Start by reading server/threads/windowsProcessTree.ts and tracing the spawn() path, then review dependencies.md for the required native-dependency justification. The replacement is done when process creation assigns and retains a Windows Job Object, termination targets its members directly, and the existing creation-time and PID-reuse heuristics are no longer needed.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
operating-systems
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.