Fix race condition in dispatcher (#2208)

* fix dispatcher race condition

Signed-off-by: Jacob Lisi <jacob.t.lisi@gmail.com>

* add test to check for race condition in dispatcher

Signed-off-by: Jacob Lisi <jacob.t.lisi@gmail.com>

* return when dispatcher Stop has nil receiver

Signed-off-by: Jacob Lisi <jacob.t.lisi@gmail.com>

* remove unneeded chec

Signed-off-by: Jacob Lisi <jacob.t.lisi@gmail.com>
This commit is contained in:
Jacob Lisi 2020-03-19 10:32:37 -04:00 committed by GitHub
parent 44af3201fe
commit 0c0c6bdb01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 3 deletions

View File

@ -111,9 +111,8 @@ func (d *Dispatcher) Run() {
d.mtx.Lock() d.mtx.Lock()
d.aggrGroups = map[*Route]map[model.Fingerprint]*aggrGroup{} d.aggrGroups = map[*Route]map[model.Fingerprint]*aggrGroup{}
d.metrics.aggrGroups.Set(0) d.metrics.aggrGroups.Set(0)
d.mtx.Unlock()
d.ctx, d.cancel = context.WithCancel(context.Background()) d.ctx, d.cancel = context.WithCancel(context.Background())
d.mtx.Unlock()
d.run(d.alerts.Subscribe()) d.run(d.alerts.Subscribe())
close(d.done) close(d.done)
@ -255,11 +254,16 @@ func (d *Dispatcher) Groups(routeFilter func(*Route) bool, alertFilter func(*typ
// Stop the dispatcher. // Stop the dispatcher.
func (d *Dispatcher) Stop() { func (d *Dispatcher) Stop() {
if d == nil || d.cancel == nil { if d == nil {
return
}
d.mtx.Lock()
if d.cancel == nil {
return return
} }
d.cancel() d.cancel()
d.cancel = nil d.cancel = nil
d.mtx.Unlock()
<-d.done <-d.done
} }

View File

@ -522,3 +522,18 @@ func newAlert(labels model.LabelSet) *types.Alert {
Timeout: false, Timeout: false,
} }
} }
func TestDispatcherRace(t *testing.T) {
logger := log.NewNopLogger()
marker := types.NewMarker(prometheus.NewRegistry())
alerts, err := mem.NewAlerts(context.Background(), marker, time.Hour, logger)
if err != nil {
t.Fatal(err)
}
defer alerts.Close()
timeout := func(d time.Duration) time.Duration { return time.Duration(0) }
dispatcher := NewDispatcher(alerts, nil, nil, marker, timeout, logger, NewDispatcherMetrics(prometheus.NewRegistry()))
go dispatcher.Run()
dispatcher.Stop()
}