Files
mattermost/app/cluster.go
Agniva De Sarker d317dd2dde MM-25154: Fix data race in InvokeClusterLeaderChangedListener (#14610)
The order of booting up a server should be
Job scheduler -> Cluster.

And shutdown should be the opposite. This is needed because the job scheduler
initializes certain data structures that are later called by ClusterLeaderChanged
event handlers. And the event handlers run in a separate goroutine.

Therefore, if the cluster initialization happens before the job scheduler,
then a race happens between accessing the jobs variable and setting it.

To prevent this race, we fix the order of startup, and add comments in both
places to prevent things from regressing again.
2020-05-22 23:52:25 +05:30

37 lines
1.3 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package app
import (
"github.com/mattermost/mattermost-server/v5/model"
)
// Registers a given function to be called when the cluster leader may have changed. Returns a unique ID for the
// listener which can later be used to remove it. If clustering is not enabled in this build, the callback will never
// be called.
func (s *Server) AddClusterLeaderChangedListener(listener func()) string {
id := model.NewId()
s.clusterLeaderListeners.Store(id, listener)
return id
}
// Removes a listener function by the unique ID returned when AddConfigListener was called
func (s *Server) RemoveClusterLeaderChangedListener(id string) {
s.clusterLeaderListeners.Delete(id)
}
func (s *Server) InvokeClusterLeaderChangedListeners() {
s.Log.Info("Cluster leader changed. Invoking ClusterLeaderChanged listeners.")
// This needs to be run in a separate goroutine otherwise a recursive lock happens
// because the listener function eventually ends up calling .IsLeader().
// Fixing this would require the changed event to pass the leader directly, but that
// requires a lot of work.
s.Go(func() {
s.clusterLeaderListeners.Range(func(_, listener interface{}) bool {
listener.(func())()
return true
})
})
}