mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-11 08:06:25 -04:00
When suspending with ctrl+z, the suspend keybinding handler disengages the screen and then sends SIGSTOP to the process group, so the UI thread freezes at the return from kill(2) with the handler's follow-up flush still pending. When fg continues the process, that pending flush races the SIGCONT handler's Resume. If the flush wins, Show() draws against the disengaged screen, whose cell buffer tcell has released to 0x0 while its width/height still hold the old size; drawCell() then reports width 0 for the out-of-range cell, the draw loop's 'x += width - 1' never advances, and the UI thread spins forever while holding the tcell screen lock. Resume in turn blocks forever on that lock, so the screen never re-engages and no input is ever read again: the hard stall of #5309, only recoverable by killing the process. Guard both flush paths with the suspended flag. For the flag to guarantee that the screen is engaged whenever it is false, Resume must clear it only after re-engaging (it used to clear it before); Suspend already sets it before disengaging. This also covers the pre-existing unsynchronized suspended check in draw(), which is subsumed by the guards and can go. The regression test cannot use the demonstrate-then-fix pattern: on unfixed code the flush goroutine spins holding the screen lock, which deadlocks any subsequent screen call including the test cleanup's Close(). |
||
|---|---|---|
| .. | ||
| app | ||
| cheatsheet | ||
| commands | ||
| common | ||
| config | ||
| constants | ||
| env | ||
| fakes | ||
| gocui | ||
| gui | ||
| i18n | ||
| integration | ||
| jsonschema | ||
| logs | ||
| snake | ||
| tasks | ||
| theme | ||
| updates | ||
| utils | ||