Files
client-go/tools/cache
Patrick Ohly 889b95a769 client-go informers: fix potential deadlock
In the unlikely situation that sharedProcessor.distribute was triggered by a
resync before sharedProcessor.run had a chance to start the listeners, the
sharedProcessor deadlocked: sharedProcessor.distribute held a read/write lock
on listenersLock while being blocked on the write to the listener's
channel. The listeners who would have read from those weren't get started
because sharedProcessor.run was blocked trying to get a read lock for
listenersLock.

This gets fixed by releasing the read/write lock in sharedProcessor.distribute
while waiting for all listeners to be started. Because either all or no
listeners are started, the existing global listenersStarted boolean is
sufficient.

The TestListenerResyncPeriods tests now runs twice, with and without the
artificial delay. It gets converted to a synctest, so it executes quickly
despite the time.Sleep calls and timing is deterministic. The enhanced log
output confirms that with the delay, the initial sync completes later:

    === RUN   TestListenerResyncPeriods
        shared_informer_test.go:236: 0s: listener3: handle: pod1
        shared_informer_test.go:236: 0s: listener3: handle: pod2
        shared_informer_test.go:236: 0s: listener1: handle: pod1
        shared_informer_test.go:236: 0s: listener1: handle: pod2
        shared_informer_test.go:236: 0s: listener2: handle: pod1
        shared_informer_test.go:236: 0s: listener2: handle: pod2
        shared_informer_test.go:236: 2s: listener2: handle: pod1
        shared_informer_test.go:236: 2s: listener2: handle: pod2
        shared_informer_test.go:236: 3s: listener3: handle: pod1
        shared_informer_test.go:236: 3s: listener3: handle: pod2
    --- PASS: TestListenerResyncPeriods (0.00s)
    === RUN   TestListenerResyncPeriodsDelayed
        shared_informer_test.go:236: 1s: listener1: handle: pod1
        shared_informer_test.go:236: 1s: listener1: handle: pod2
        shared_informer_test.go:236: 1s: listener2: handle: pod1
        shared_informer_test.go:236: 1s: listener2: handle: pod2
        shared_informer_test.go:236: 1s: listener3: handle: pod1
        shared_informer_test.go:236: 1s: listener3: handle: pod2
        shared_informer_test.go:236: 2s: listener2: handle: pod1
        shared_informer_test.go:236: 2s: listener2: handle: pod2
        shared_informer_test.go:236: 3s: listener3: handle: pod1
        shared_informer_test.go:236: 3s: listener3: handle: pod2
    --- PASS: TestListenerResyncPeriodsDelayed (0.00s)

Kubernetes-commit: e6ef79b2f6bb05205652e4fe48ffa523d9e3a1ec
2026-01-23 19:38:52 +01:00
..
2022-02-11 14:50:19 -05:00
2024-12-02 14:43:58 +01:00