Skip to content

Commit cf12923

Browse files
committed
🐛 Controller.Watch() should not store watches if already started
The controller internal struct holds a list of watches (as []watchDescription) when someone calls .Watch() to then start the watches and informers once we're ready to call Start(). This behavior caused a memory leak in the case Watch was called after a controller has already been started and if the source.Kind's cache was either stopped or not available any longer. The leak was caused by the watches internal slice holding on to all references to each watch ever issued (and their respective caches). Signed-off-by: Vince Prignano <[email protected]>
1 parent d6829e9 commit cf12923

File tree

1 file changed

+9
-5
lines changed

1 file changed

+9
-5
lines changed

pkg/internal/controller/controller.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,14 @@ func (c *Controller) Watch(src source.Source, evthdler handler.EventHandler, prc
113113
}
114114
}
115115

116-
c.watches = append(c.watches, watchDescription{src: src, handler: evthdler, predicates: prct})
117-
if c.Started {
118-
c.Log.Info("Starting EventSource", "source", src)
119-
return src.Start(evthdler, c.Queue, prct...)
116+
// Controller hasn't started yet, store the watches locally and return.
117+
if !c.Started {
118+
c.watches = append(c.watches, watchDescription{src: src, handler: evthdler, predicates: prct})
119+
return nil
120120
}
121121

122-
return nil
122+
c.Log.Info("Starting EventSource", "source", src)
123+
return src.Start(evthdler, c.Queue, prct...)
123124
}
124125

125126
// Start implements controller.Controller
@@ -167,6 +168,9 @@ func (c *Controller) Start(stop <-chan struct{}) error {
167168
}
168169
}
169170

171+
// All the watches have been started, we can reset the local slice.
172+
c.watches = nil
173+
170174
if c.JitterPeriod == 0 {
171175
c.JitterPeriod = 1 * time.Second
172176
}

0 commit comments

Comments
 (0)