From faa6a350c8a5a2060e22eac262cd0600804b7852 Mon Sep 17 00:00:00 2001 From: Hunter Herman Date: Sat, 3 Dec 2022 10:32:03 -0800 Subject: [PATCH] Fixes deadlock between Mouse cuts and xfideventread When cutting with the mouse it was possible for: 1. Text select to release the biglock, while maintaining a winlock 2. xfideventread to then acquire the biglock, and wait for the winlock Deadlocking. After fixing this deadlock, the following appeared: 1. xfideventwrite releases the big lock, but holds the winlock 2. Text select reacqiures the big lock and blocks on the winlock Another deadlock. --- cmd/acme/internal/ui/text.go | 10 ++++++++-- cmd/acme/xfid.go | 3 +++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/cmd/acme/internal/ui/text.go b/cmd/acme/internal/ui/text.go index 64fcc9a..1260eff 100644 --- a/cmd/acme/internal/ui/text.go +++ b/cmd/acme/internal/ui/text.go @@ -473,17 +473,23 @@ func Textselect(t *wind.Text) { // Do just the receive, dropping biglock // to let other goroutines proceed. // Note that *Mouse is Mousectl.Mouse. + // We also need to release the window lock, or else other code + // will deadlock with us by acquiring the big lock and _then_ acquiring + // the window lock + o := t.W.Owner + wind.Winunlock(t.W) BigUnlock() for Mouse.Buttons == b { *Mouse = <-Mousectl.C } BigLock() + wind.Winlock(t.W, o) clicktext = nil } } -var BigLock = func(){} -var BigUnlock = func(){} +var BigLock = func() {} +var BigUnlock = func() {} /* * Release the button in less than DELAY ms and it's considered a null selection diff --git a/cmd/acme/xfid.go b/cmd/acme/xfid.go index 892944a..9e5d6b3 100644 --- a/cmd/acme/xfid.go +++ b/cmd/acme/xfid.go @@ -846,9 +846,12 @@ func xfideventwrite(x *Xfid, w *wind.Window) { goto Rescue } + o := w.Owner + wind.Winunlock(w) bigUnlock() wind.TheRow.Lk.Lock() // just like mousethread bigLock() + wind.Winlock(w, o) switch c { case 'x', 'X':