diff options
author | Tim Culverhouse <tim@timculverhouse.com> | 2022-09-16 14:41:05 -0500 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2022-09-20 00:03:36 +0200 |
commit | f4d6ade429850aa30b5f6a8aefc3ef5a00c2e584 (patch) | |
tree | 0d2b97ffe799f9a5afee2b9a94eb0b0a4f2e0724 /worker | |
parent | e808b96d63ecab9990cbb295e786010be66243be (diff) | |
download | aerc-f4d6ade429850aa30b5f6a8aefc3ef5a00c2e584.tar.gz |
imap: prevent deadlock from posting actions to self
The IMAP worker has a few methods that post a new Action to itself. This
can create a deadlock when the worker.Actions channel is full: The
worker can't accept a new Action because it's trying to post an action.
This is most noticeable when cached headers are enabled and the message
list is scrolled fast.
Use a goroutine to post actions to the worker when posting from within
the worker.
Fixes: https://todo.sr.ht/~rjarry/aerc/45
Fixes: 7aa71d334b27 ("imap: add option to cache headers")
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Diffstat (limited to 'worker')
-rw-r--r-- | worker/imap/cache.go | 3 | ||||
-rw-r--r-- | worker/imap/flags.go | 6 | ||||
-rw-r--r-- | worker/types/worker.go | 4 |
3 files changed, 10 insertions, 3 deletions
diff --git a/worker/imap/cache.go b/worker/imap/cache.go index 62d450e6..3c807c50 100644 --- a/worker/imap/cache.go +++ b/worker/imap/cache.go @@ -126,7 +126,8 @@ func (w *IMAPWorker) getCachedHeaders(msg *types.FetchMessageHeaders) []uint32 { }, nil) } if len(found) > 0 { - w.worker.PostAction(&types.FetchMessageFlags{ + // Post in a separate goroutine to prevent deadlocking + go w.worker.PostAction(&types.FetchMessageFlags{ Uids: found, }, nil) } diff --git a/worker/imap/flags.go b/worker/imap/flags.go index bda47e9d..0cd0bb78 100644 --- a/worker/imap/flags.go +++ b/worker/imap/flags.go @@ -48,7 +48,8 @@ func (imapw *IMAPWorker) handleAnsweredMessages(msg *types.AnsweredMessages) { emitErr(err) return } - imapw.worker.PostAction(&types.FetchMessageHeaders{ + // Post in a separate goroutine to prevent deadlocking + go imapw.worker.PostAction(&types.FetchMessageHeaders{ Uids: msg.Uids, }, func(_msg types.WorkerMessage) { switch m := _msg.(type) { @@ -79,7 +80,8 @@ func (imapw *IMAPWorker) handleFlagMessages(msg *types.FlagMessages) { emitErr(err) return } - imapw.worker.PostAction(&types.FetchMessageHeaders{ + // Post in a separate goroutine to prevent deadlocking + go imapw.worker.PostAction(&types.FetchMessageHeaders{ Uids: msg.Uids, }, func(_msg types.WorkerMessage) { switch m := _msg.(type) { diff --git a/worker/types/worker.go b/worker/types/worker.go index 9e247982..ba396aa3 100644 --- a/worker/types/worker.go +++ b/worker/types/worker.go @@ -35,6 +35,8 @@ func (worker *Worker) setId(msg WorkerMessage) { msg.setId(id) } +// PostAction posts an action to the worker. This method should not be called +// from the same goroutine that the worker runs in or deadlocks may occur func (worker *Worker) PostAction(msg WorkerMessage, cb func(msg WorkerMessage)) { worker.setId(msg) @@ -50,6 +52,8 @@ func (worker *Worker) PostAction(msg WorkerMessage, cb func(msg WorkerMessage)) } } +// PostMessage posts an message to the UI. This method should not be called +// from the same goroutine that the UI runs in or deadlocks may occur func (worker *Worker) PostMessage(msg WorkerMessage, cb func(msg WorkerMessage), ) { |