Skip to content

Commit 9be012b

Browse files
Jonathan S. Katzjkatz
authored andcommitted
Fixed race condition with adding schedules
The multi-namespace functionality created a situation in the scheduler where an informer would be created twice on the same namespace. This would result in two entries in the schedule table being added, which then resulted in only one of the schedule entries being removed. As such "phantom scheduled events" would occur. This patch borrows a pattern from the controllers that creates a mutex on the informer creation function and only allows a single informer to be created on a namespace at a given time. Issue: [ch6933] Issue: #1215
1 parent 764414b commit 9be012b

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

pgo-scheduler/pgo-scheduler.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"os"
2020
"os/signal"
2121
"strconv"
22+
"sync"
2223
"syscall"
2324
"time"
2425

@@ -49,6 +50,11 @@ var timeout time.Duration
4950
var seconds int
5051
var kubeClient *kubernetes.Clientset
5152

53+
// this is used to prevent a race condition where an informer is being created
54+
// twice when a new scheduler-enabled ConfigMap is added.
55+
var informerNsMutex sync.Mutex
56+
var informerNamespaces map[string]struct{}
57+
5258
func init() {
5359
var err error
5460
log.SetLevel(log.InfoLevel)
@@ -70,6 +76,11 @@ func init() {
7076
log.Info("PGO_INSTALLATION_NAME set to " + installationName)
7177
}
7278

79+
// set up the data structures for preventing double informers from being
80+
// created
81+
informerNsMutex = sync.Mutex{}
82+
informerNamespaces = map[string]struct{}{}
83+
7384
pgoNamespace = os.Getenv(pgoNamespaceEnv)
7485
if pgoNamespace == "" {
7586
log.WithFields(log.Fields{}).Fatalf("Failed to get PGO_OPERATOR_NAMESPACE environment: %s", pgoNamespaceEnv)
@@ -162,6 +173,17 @@ func newKubeClient() (*kubernetes.Clientset, error) {
162173
}
163174

164175
func SetupWatch(namespace string, scheduler *scheduler.Scheduler, stop chan struct{}) {
176+
// don't create informer for namespace if one has already been created
177+
informerNsMutex.Lock()
178+
defer informerNsMutex.Unlock()
179+
180+
// if the namespace is already in the informer namespaces map, then exit
181+
if _, ok := informerNamespaces[namespace]; ok {
182+
return
183+
}
184+
185+
informerNamespaces[namespace] = struct{}{}
186+
165187
watchlist := cache.NewListWatchFromClient(kubeClient.Core().RESTClient(),
166188
"configmaps", namespace, fields.Everything())
167189

0 commit comments

Comments
 (0)