Files
orca/config
Neil ca272a78c0 fix(daemon): read the PTY process table without blocking on terminal kill and resize (#34603)
* fix(daemon): read the PTY process table without blocking on terminal kill and resize

The terminal daemon force-killed a session by running ps and reading
/proc/<pid>/stat synchronously, and checked the resize foreground group
with execFileSync('ps'). A slow or wedged ps froze every terminal the
daemon serves for up to the ps timeout on each call.

Both paths now use the async process-table read (runProcess with a
timeout that kills the child). SubprocessHandle.forceKill may return a
promise; the termination controller awaits it so a refused signal still
releases the claim for a retry. A force-kill or SIGWINCH whose root
exits while ps runs signals nothing, since the captured groups could
already be recycled. ConPTY force-kill stays synchronous so dispose()
still sees the node-pty kill it must not repeat. The in-process
provider's app-quit sweep keeps the blocking variant. The ps dialect
and table readers move to posix-pty-process-table.ts.

Refs #34410
Refs #33870

* fix(daemon): address review on async PTY process-table reads

Guard only the root-pid fallback on exit so proven groups are still swept
after dispose, wait out at most one ps dialect probe, move the sync-launch
baseline entry with the table reader, and keep tests cross-platform.

Refs #34410
Refs #33870

* fix(daemon): keep the PTY open until an in-flight force-kill sweep finishes

A sweep whose root exits mid-read must not signal: the freed TTY may
belong to another terminal. Dispose therefore defers destroy() until the
sweep settles, so its hangup cannot end the root first.

Refs #34410
Refs #33870

* test(daemon): build the destroy-tracking PTY mock without a type assertion

Refs #34410
Refs #33870

* fix(pty): make the local graceful-deadline force-kill async and stub ps in tests

The in-process provider's graceful-deadline timer now uses the async
group sweep; the app-quit sweep and the root-signal path stay
synchronous. Tests that drove force-kill through fixture pids now stub
the async process-table read instead of querying the host, and a new
test pins that waiters do not chain behind a failed dialect probe.
Session ids are only read for rows on the root's terminal.

Refs #34410
Refs #33870

* fix(pty): hold PTY teardown until an in-flight force-kill sweep settles

Orphan cleanup could destroy a local PTY while the graceful-deadline
sweep was still reading the process table, neutralizing its fallback
kill and hanging up the root first. Both the daemon handle and the
local provider now defer teardown through PendingPtyGroupSweep.

Concurrent force-kill callers in the daemon now await the shared
in-flight request, so a joiner's physical-exit budget starts after the
signals are sent and it sees their rejection.

Refs #34410
Refs #33870

* fix(pty): let disposal and orphan cleanup join the in-flight force-kill sweep

Session disposal now joins the controller's shared force-kill request
instead of starting a second sweep. Local orphan cleanup decides its
escalation only after a pending graceful-deadline sweep settles, so a
refused sweep is escalated before the handle is released rather than
leaving the retry with a neutralized kill.

Refs #34410
Refs #33870

* fix(daemon): SIGKILL live PTY groups before a shutdown deadline exit

The old synchronous sweep sent its signals before the shutdown deadline
timer could run; the async sweep can still be reading the process table
when it fires. The deadline now SIGKILLs each live session's process
group synchronously before exiting (node-pty roots lead their own
group), falling back to the root pid when the group kill is refused.
POSIX only.

Refs #34410
Refs #33870
2026-10-27 18:36:30 -07:00
..