msgstore: fix data race on access to store.needsFlags

Flag fetching is debounced in the UI, creating a race condition where
fields are accessed in the AfterFunc. Protect the needsFlags field with
a mutex.

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
Tim Culverhouse 2022-09-29 16:27:05 -05:00 committed by Robin Jarry
parent dc299cc8ad
commit 8cd4770f32

View file

@ -14,6 +14,7 @@ import (
// Accesses to fields must be guarded by MessageStore.Lock/Unlock // Accesses to fields must be guarded by MessageStore.Lock/Unlock
type MessageStore struct { type MessageStore struct {
sync.Mutex
Deleted map[uint32]interface{} Deleted map[uint32]interface{}
DirInfo models.DirectoryInfo DirInfo models.DirectoryInfo
Messages map[uint32]*models.MessageInfo Messages map[uint32]*models.MessageInfo
@ -247,7 +248,9 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {
store.Messages[msg.Info.Uid] = msg.Info store.Messages[msg.Info.Uid] = msg.Info
} }
if msg.NeedsFlags { if msg.NeedsFlags {
store.Lock()
store.needsFlags = append(store.needsFlags, msg.Info.Uid) store.needsFlags = append(store.needsFlags, msg.Info.Uid)
store.Unlock()
store.fetchFlags() store.fetchFlags()
} }
seen := false seen := false
@ -757,9 +760,11 @@ func (store *MessageStore) fetchFlags() {
store.fetchFlagsDebounce.Stop() store.fetchFlagsDebounce.Stop()
} }
store.fetchFlagsDebounce = time.AfterFunc(store.fetchFlagsDelay, func() { store.fetchFlagsDebounce = time.AfterFunc(store.fetchFlagsDelay, func() {
store.Lock()
store.worker.PostAction(&types.FetchMessageFlags{ store.worker.PostAction(&types.FetchMessageFlags{
Uids: store.needsFlags, Uids: store.needsFlags,
}, nil) }, nil)
store.needsFlags = []uint32{} store.needsFlags = []uint32{}
store.Unlock()
}) })
} }