mirror of
https://github.com/kubernetes/client-go.git
synced 2025-06-29 16:36:54 +00:00
informer: fix race against Run and SetTransform/SetWatchErrorHandler
`SetWatchErrorHandler` claims it will fail if Run() has already started. But if they are called concurrently, it will actually trigger a data race. With this PR: ``` 62702 runs so far, 0 failures (100.00% pass rate). 59.152682ms avg, 189.068387ms max, 26.623785ms min ``` Without this PR: ``` 5012 runs so far, 38 failures (99.25% pass rate). 58.675502ms avg, 186.018084ms max, 29.468104ms min ``` Kubernetes-commit: 35d2431b3a89c5bd693846952e9d27ce4e3a0754
This commit is contained in:
parent
cf830e3cb3
commit
702d7378b6
9
tools/cache/shared_informer.go
vendored
9
tools/cache/shared_informer.go
vendored
@ -459,6 +459,11 @@ func (s *sharedIndexInformer) Run(stopCh <-chan struct{}) {
|
|||||||
klog.Warningf("The sharedIndexInformer has started, run more than once is not allowed")
|
klog.Warningf("The sharedIndexInformer has started, run more than once is not allowed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func() {
|
||||||
|
s.startedLock.Lock()
|
||||||
|
defer s.startedLock.Unlock()
|
||||||
|
|
||||||
fifo := NewDeltaFIFOWithOptions(DeltaFIFOOptions{
|
fifo := NewDeltaFIFOWithOptions(DeltaFIFOOptions{
|
||||||
KnownObjects: s.indexer,
|
KnownObjects: s.indexer,
|
||||||
EmitDeltaTypeReplaced: true,
|
EmitDeltaTypeReplaced: true,
|
||||||
@ -478,10 +483,6 @@ func (s *sharedIndexInformer) Run(stopCh <-chan struct{}) {
|
|||||||
WatchErrorHandler: s.watchErrorHandler,
|
WatchErrorHandler: s.watchErrorHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
func() {
|
|
||||||
s.startedLock.Lock()
|
|
||||||
defer s.startedLock.Unlock()
|
|
||||||
|
|
||||||
s.controller = New(cfg)
|
s.controller = New(cfg)
|
||||||
s.controller.(*controller).clock = s.clock
|
s.controller.(*controller).clock = s.clock
|
||||||
s.started = true
|
s.started = true
|
||||||
|
27
tools/cache/shared_informer_test.go
vendored
27
tools/cache/shared_informer_test.go
vendored
@ -393,6 +393,33 @@ func TestSharedInformerErrorHandling(t *testing.T) {
|
|||||||
close(stop)
|
close(stop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestSharedInformerStartRace is a regression test to ensure there is no race between
|
||||||
|
// Run and SetWatchErrorHandler, and Run and SetTransform.
|
||||||
|
func TestSharedInformerStartRace(t *testing.T) {
|
||||||
|
source := fcache.NewFakeControllerSource()
|
||||||
|
informer := NewSharedInformer(source, &v1.Pod{}, 1*time.Second).(*sharedIndexInformer)
|
||||||
|
stop := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-stop:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
// Set dummy functions, just to test for race
|
||||||
|
informer.SetTransform(func(i interface{}) (interface{}, error) {
|
||||||
|
return i, nil
|
||||||
|
})
|
||||||
|
informer.SetWatchErrorHandler(func(r *Reflector, err error) {
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
go informer.Run(stop)
|
||||||
|
|
||||||
|
close(stop)
|
||||||
|
}
|
||||||
|
|
||||||
func TestSharedInformerTransformer(t *testing.T) {
|
func TestSharedInformerTransformer(t *testing.T) {
|
||||||
// source simulates an apiserver object endpoint.
|
// source simulates an apiserver object endpoint.
|
||||||
source := fcache.NewFakeControllerSource()
|
source := fcache.NewFakeControllerSource()
|
||||||
|
Loading…
Reference in New Issue
Block a user