MM-30987- Fix race in setting clearNotify in Busy (#16430)

A time.AfterFunc runs the function in its own goroutine. So we need
to guard that with a mutex too.

https://mattermost.atlassian.net/browse/MM-30987

```release-note
NONE
```
This commit is contained in:
Agniva De Sarker
2020-12-02 08:49:40 +05:30
committed by GitHub
parent 3fdc6cb531
commit 6ed90bf1db
2 changed files with 15 additions and 1 deletions

View File

@@ -65,7 +65,11 @@ func (b *Busy) setWithoutNotify(dur time.Duration) {
b.clearWithoutNotify()
atomic.StoreInt32(&b.busy, 1)
b.expires = time.Now().Add(dur)
b.timer = time.AfterFunc(dur, b.clearWithoutNotify)
b.timer = time.AfterFunc(dur, func() {
b.mux.Lock()
b.clearWithoutNotify()
b.mux.Unlock()
})
}
// ClearBusy marks the server as not busy and notifies cluster nodes.

View File

@@ -86,6 +86,16 @@ func TestBusyExpires(t *testing.T) {
require.Eventually(t, func() bool { return compareBusyState(t, busy, cluster.Busy) }, time.Second*15, time.Millisecond*20)
}
func TestBusyRace(t *testing.T) {
cluster := &ClusterMock{Busy: &Busy{}}
busy := NewBusy(cluster)
busy.Set(500 * time.Millisecond)
// We are sleeping in order to let the race trigger.
time.Sleep(time.Second)
}
func compareBusyState(t *testing.T, busy1 *Busy, busy2 *Busy) bool {
t.Helper()
if busy1.IsBusy() != busy2.IsBusy() {