Avoid holding mutex while waking main loop on wait unblock

Sending to serverInputChan while holding t.mutex could deadlock: if the
channel fills, the send blocks with the mutex held while the main loop
waits on the same mutex and can't drain the channel.

Capture the wake-up need under the lock, send after releasing it.
This commit is contained in:
Junegunn Choi
2026-06-29 09:12:21 +09:00
parent 57d1a3d237
commit 5b4afa0447
+9 -3
View File
@@ -1882,14 +1882,13 @@ func (t *Terminal) UpdateList(result MatchResult) {
merger := result.merger
t.mutex.Lock()
waitWasBlocked := t.waitBlocked
wakeUp := false
if result.final() {
t.searchInProgress = false
// If waiting, unblock so main loop can execute pending actions
if t.waitBlocked {
t.unblockWait()
if len(t.pendingActions) > 0 {
t.serverInputChan <- []*action{{t: actIgnore}}
}
wakeUp = len(t.pendingActions) > 0
}
}
prevIndex := minItem.Index()
@@ -2060,6 +2059,13 @@ func (t *Terminal) UpdateList(result MatchResult) {
updatePrompt := (trackWasBlocked && !t.trackBlocked) || (waitWasBlocked && !t.waitBlocked)
t.mutex.Unlock()
// Wake up the main loop to execute pending actions after wait unblocks.
// Send after releasing the mutex to avoid blocking on a full channel
// while holding it.
if wakeUp {
t.serverInputChan <- []*action{{t: actIgnore}}
}
t.reqBox.Set(reqInfo, nil)
if updateList {
t.reqBox.Set(reqList, nil)