mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-10 07:36:27 -04:00
Stopping a pty task on Windows relies on ClosePseudoConsole, which delivers CTRL_CLOSE_EVENT to the console's attached clients. But only to those attached at that moment: when the user flicks quickly through commits, a task is often stopped within the first few milliseconds of its life, before the child has attached to the pseudoconsole. Such a child misses the event and survives, running the entire diff to completion in the background (spawning one external differ per changed file) and keeping its conhost.exe alive; rapid navigation accumulates these git/difft/conhost trees, and they outlive lazygit. Grandchildren are affected too: git for Windows runs commands through a two-level git.exe wrapper, so a single task has several attach windows, and a grandchild spawned while the console is going down is orphaned even when its parent got the event and exited. Fix this by putting the child into a job object before it runs its first instruction (created suspended, assigned, then resumed), so that every descendant is in the job from the start; the teardown in Close terminates the job right after initiating the pseudoconsole close. There is no point in a grace period between the two: the close event is not a graceful signal -- git and the common diff tools leave it to the default handler, which calls ExitProcess at an arbitrary point -- so clients that received it are already dying, and the kill exists for those that missed it. Killing at an arbitrary point cannot leak a stale index.lock, because pty-rendered commands no longer take that lock (see withPtyGitConfig in pkg/gui/pty.go). The pseudoconsole close runs on its own goroutine because the kill must not wait for it: on builds where ClosePseudoConsole blocks until the console host exits (pre-24H2), the host keeps running as long as a surviving client does, and that client only goes away through the job kill; sequencing the kill after a blocking close would deadlock in exactly the case the kill exists for. KILL_ON_JOB_CLOSE doubles as a safety net: if lazygit exits without running the teardown, the OS closes the job handle and reaps the tree. In a harness that mimicked the stop path with randomized 0-120ms stop delays, 3 of 30 process trees survived as orphans before this change; none survive with it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| app | ||
| cheatsheet | ||
| commands | ||
| common | ||
| config | ||
| constants | ||
| env | ||
| fakes | ||
| gocui | ||
| gui | ||
| i18n | ||
| integration | ||
| jsonschema | ||
| logs | ||
| snake | ||
| tasks | ||
| theme | ||
| updates | ||
| utils | ||