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 ```
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
3fdc6cb531
Коммит
6ed90bf1db
@@ -65,7 +65,11 @@ func (b *Busy) setWithoutNotify(dur time.Duration) {
|
|||||||
b.clearWithoutNotify()
|
b.clearWithoutNotify()
|
||||||
atomic.StoreInt32(&b.busy, 1)
|
atomic.StoreInt32(&b.busy, 1)
|
||||||
b.expires = time.Now().Add(dur)
|
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.
|
// ClearBusy marks the server as not busy and notifies cluster nodes.
|
||||||
|
|||||||
@@ -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)
|
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 {
|
func compareBusyState(t *testing.T, busy1 *Busy, busy2 *Busy) bool {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if busy1.IsBusy() != busy2.IsBusy() {
|
if busy1.IsBusy() != busy2.IsBusy() {
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user