Skip to content

Commit f89fe47

Browse files
committed
🐛 Event recorder should not send events when broadcaster is stopped
This change solves a race condition when the manager is shutting down and reconcilers are still in the process of sending events through the recorder. If the shutdown timeout is hit too early, the event recorder panics because we're still trying to send events through the recorder. To avoid this issue, we introduce a RWMutex between the provider and event recorder. When the broadcaster is shutdown, events are now dropped. Signed-off-by: Vince Prignano <[email protected]>
1 parent 197751d commit f89fe47

File tree

1 file changed

+24
-3
lines changed

1 file changed

+24
-3
lines changed

pkg/internal/recorder/recorder.go

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ type EventBroadcasterProducer func() (caster record.EventBroadcaster, stopWithPr
3838
// Provider is a recorder.Provider that records events to the k8s API server
3939
// and to a logr Logger.
4040
type Provider struct {
41+
lock sync.RWMutex
42+
stopped bool
43+
4144
// scheme to specify when creating a recorder
4245
scheme *runtime.Scheme
4346
// logger is the logger to use when logging diagnostic event info
@@ -70,7 +73,10 @@ func (p *Provider) Stop(shutdownCtx context.Context) {
7073
// an invocation of getBroadcaster.
7174
broadcaster := p.getBroadcaster()
7275
if p.stopBroadcaster {
76+
p.lock.Lock()
7377
broadcaster.Shutdown()
78+
p.stopped = true
79+
p.lock.Unlock()
7480
}
7581
close(doneCh)
7682
}()
@@ -144,13 +150,28 @@ func (l *lazyRecorder) ensureRecording() {
144150

145151
func (l *lazyRecorder) Event(object runtime.Object, eventtype, reason, message string) {
146152
l.ensureRecording()
147-
l.rec.Event(object, eventtype, reason, message)
153+
154+
l.prov.lock.RLock()
155+
if !l.prov.stopped {
156+
l.rec.Event(object, eventtype, reason, message)
157+
}
158+
l.prov.lock.RUnlock()
148159
}
149160
func (l *lazyRecorder) Eventf(object runtime.Object, eventtype, reason, messageFmt string, args ...interface{}) {
150161
l.ensureRecording()
151-
l.rec.Eventf(object, eventtype, reason, messageFmt, args...)
162+
163+
l.prov.lock.RLock()
164+
if !l.prov.stopped {
165+
l.rec.Eventf(object, eventtype, reason, messageFmt, args...)
166+
}
167+
l.prov.lock.RUnlock()
152168
}
153169
func (l *lazyRecorder) AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) {
154170
l.ensureRecording()
155-
l.rec.AnnotatedEventf(object, annotations, eventtype, reason, messageFmt, args...)
171+
172+
l.prov.lock.RLock()
173+
if !l.prov.stopped {
174+
l.rec.AnnotatedEventf(object, annotations, eventtype, reason, messageFmt, args...)
175+
}
176+
l.prov.lock.RUnlock()
156177
}

0 commit comments

Comments
 (0)