An old ~/.local/bin/cursor-agent that runs `cursor agent`, which (Cursor's
own bin/cursor) first runs ~/.local/bin/cursor-agent --min-version=... status,
calls itself without end. magpie asks cursor-agent who is signed in (about,
10s timeout) and kills the probe's session on the timeout with one SIGKILL
to the group. On macOS that one signal can miss a process being forked as it
goes out; the miss lives on, in the same group, adopted by init, and keeps
calling itself until the user can start no process (JJ-Lin: ~4800 bash
processes in one chain whose root's parent is PID 1). group.kill now sends
SIGKILL to the group again every 5ms, behind the caller, until the group is
gone (ESRCH) or 10s pass. The group keeps its id while any of it lives, so
nothing else is signalled. It covers ProbeContext's timeout and EndProbes,
and StartTree's Kill and sweep.
Verified:
- red without the change: TestProbeKillEndsWhatTheSignalMissed (the first
group signal is made to miss, as the race does) fails with
"what the probe started (pid 95576) outlived a kill that missed it once";
passes with it (-count=5).
- reproduced the leak with the real Cursor 3.12.6 launcher script
(/Applications/Cursor.app/.../bin/cursor, read only) and JJ-Lin's 87-byte
wrapper in a sandbox HOME, under ulimit -u: ProbeContext(cursor-agent about)
with a 10s timeout peaked at 311-700 processes; before the change 1 of 3
runs left a chain behind (root ppid 1, same pgid, args
"agent --min-version=2025.10.01 status"), after it 0 of 6. A fake
launcher (60 parallel self-calling chains, killed at 500ms) left survivors
4 of 30 runs before, 0 of 30 after.
- the same through provider.askCursorStatus with the real launcher, 5 runs:
no cursor process left after each.
- go test -tags nogui ./internal/proc/ in a sandbox HOME; go vet -tags nogui
of proc for darwin, linux and windows.