@@ -386,13 +386,13 @@ var _ = Describe("controller", func() {
386
386
})
387
387
})
388
388
389
- Describe ("startEventSources " , func () {
389
+ Describe ("startEventSourcesLocked " , func () {
390
390
It ("should return nil when no sources are provided" , func () {
391
391
ctx , cancel := context .WithCancel (context .Background ())
392
392
defer cancel ()
393
393
394
394
ctrl .startWatches = []source.TypedSource [reconcile.Request ]{}
395
- err := ctrl .startEventSources (ctx )
395
+ err := ctrl .startEventSourcesLocked (ctx )
396
396
Expect (err ).NotTo (HaveOccurred ())
397
397
})
398
398
@@ -409,7 +409,7 @@ var _ = Describe("controller", func() {
409
409
// Set a sufficiently long timeout to avoid timeouts interfering with the error being returned
410
410
ctrl .CacheSyncTimeout = 5 * time .Second
411
411
ctrl .startWatches = []source.TypedSource [reconcile.Request ]{src }
412
- err := ctrl .startEventSources (ctx )
412
+ err := ctrl .startEventSourcesLocked (ctx )
413
413
Expect (err ).To (Equal (expectedErr ))
414
414
})
415
415
@@ -423,7 +423,7 @@ var _ = Describe("controller", func() {
423
423
ctrl .Name = "test-controller"
424
424
ctrl .CacheSyncTimeout = 5 * time .Second
425
425
426
- err := ctrl .startEventSources (ctx )
426
+ err := ctrl .startEventSourcesLocked (ctx )
427
427
Expect (err ).To (HaveOccurred ())
428
428
Expect (err .Error ()).To (ContainSubstring ("failed to wait for test-controller caches to sync" ))
429
429
})
@@ -439,7 +439,7 @@ var _ = Describe("controller", func() {
439
439
ctrl .Name = "test-controller"
440
440
ctrl .CacheSyncTimeout = 5 * time .Second
441
441
442
- err := ctrl .startEventSources (ctx )
442
+ err := ctrl .startEventSourcesLocked (ctx )
443
443
Expect (err ).NotTo (HaveOccurred ())
444
444
})
445
445
@@ -463,7 +463,7 @@ var _ = Describe("controller", func() {
463
463
startErrCh := make (chan error )
464
464
go func () {
465
465
defer GinkgoRecover ()
466
- startErrCh <- ctrl .startEventSources (sourceCtx )
466
+ startErrCh <- ctrl .startEventSourcesLocked (sourceCtx )
467
467
}()
468
468
469
469
// Allow source to start successfully
@@ -498,7 +498,7 @@ var _ = Describe("controller", func() {
498
498
499
499
ctrl .startWatches = []source.TypedSource [reconcile.Request ]{blockingSrc }
500
500
501
- err := ctrl .startEventSources (ctx )
501
+ err := ctrl .startEventSourcesLocked (ctx )
502
502
Expect (err ).To (HaveOccurred ())
503
503
Expect (err .Error ()).To (ContainSubstring ("timed out waiting for source" ))
504
504
})
@@ -517,13 +517,13 @@ var _ = Describe("controller", func() {
517
517
518
518
ctrl .startWatches = []source.TypedSource [reconcile.Request ]{src }
519
519
520
- By ("Calling startEventSources multiple times in parallel" )
520
+ By ("Calling startEventSourcesLocked multiple times in parallel" )
521
521
var wg sync.WaitGroup
522
522
for i := 1 ; i <= 5 ; i ++ {
523
523
wg .Add (1 )
524
524
go func () {
525
525
defer wg .Done ()
526
- err := ctrl .startEventSources (ctx )
526
+ err := ctrl .startEventSourcesLocked (ctx )
527
527
// All calls should return the same nil error
528
528
Expect (err ).NotTo (HaveOccurred ())
529
529
}()
@@ -533,12 +533,12 @@ var _ = Describe("controller", func() {
533
533
Expect (startCount .Load ()).To (Equal (int32 (1 )), "Source should only be started once even when called multiple times" )
534
534
})
535
535
536
- It ("should block subsequent calls from returning until the first call to startEventSources has returned" , func () {
536
+ It ("should block subsequent calls from returning until the first call to startEventSourcesLocked has returned" , func () {
537
537
ctx , cancel := context .WithCancel (context .Background ())
538
538
defer cancel ()
539
539
ctrl .CacheSyncTimeout = 5 * time .Second
540
540
541
- // finishSourceChan is closed to unblock startEventSources from returning
541
+ // finishSourceChan is closed to unblock startEventSourcesLocked from returning
542
542
finishSourceChan := make (chan struct {})
543
543
544
544
src := source .Func (func (ctx context.Context , _ workqueue.TypedRateLimitingInterface [reconcile.Request ]) error {
@@ -547,28 +547,28 @@ var _ = Describe("controller", func() {
547
547
})
548
548
ctrl .startWatches = []source.TypedSource [reconcile.Request ]{src }
549
549
550
- By ("Calling startEventSources asynchronously" )
550
+ By ("Calling startEventSourcesLocked asynchronously" )
551
551
go func () {
552
552
defer GinkgoRecover ()
553
- Expect (ctrl .startEventSources (ctx )).To (Succeed ())
553
+ Expect (ctrl .startEventSourcesLocked (ctx )).To (Succeed ())
554
554
}()
555
555
556
- By ("Calling startEventSources again" )
556
+ By ("Calling startEventSourcesLocked again" )
557
557
var didSubsequentCallComplete atomic.Bool
558
558
go func () {
559
559
defer GinkgoRecover ()
560
- Expect (ctrl .startEventSources (ctx )).To (Succeed ())
560
+ Expect (ctrl .startEventSourcesLocked (ctx )).To (Succeed ())
561
561
didSubsequentCallComplete .Store (true )
562
562
}()
563
563
564
- // Assert that second call to startEventSources is blocked while source has not finished
564
+ // Assert that second call to startEventSourcesLocked is blocked while source has not finished
565
565
Consistently (didSubsequentCallComplete .Load ).Should (BeFalse ())
566
566
567
567
By ("Finishing source start + sync" )
568
568
finishSourceChan <- struct {}{}
569
569
570
- // Assert that second call to startEventSources is now complete
571
- Eventually (didSubsequentCallComplete .Load ).Should (BeTrue (), "startEventSources should complete after source is started and synced" )
570
+ // Assert that second call to startEventSourcesLocked is now complete
571
+ Eventually (didSubsequentCallComplete .Load ).Should (BeTrue (), "startEventSourcesLocked should complete after source is started and synced" )
572
572
})
573
573
574
574
It ("should reset c.startWatches to nil after returning" , func () {
@@ -583,7 +583,7 @@ var _ = Describe("controller", func() {
583
583
584
584
ctrl .startWatches = []source.TypedSource [reconcile.Request ]{src }
585
585
586
- err := ctrl .startEventSources (ctx )
586
+ err := ctrl .startEventSourcesLocked (ctx )
587
587
Expect (err ).NotTo (HaveOccurred ())
588
588
Expect (ctrl .startWatches ).To (BeNil (), "startWatches should be reset to nil after returning" )
589
589
})
@@ -1236,6 +1236,31 @@ var _ = Describe("controller", func() {
1236
1236
Expect (<- runnableExecutionOrderChan ).To (Equal (nonWarmupRunnableName ))
1237
1237
})
1238
1238
1239
+ It ("should not cause a data race when called concurrently" , func () {
1240
+ ctx , cancel := context .WithCancel (context .Background ())
1241
+ defer cancel ()
1242
+
1243
+ ctrl .CacheSyncTimeout = time .Second
1244
+
1245
+ ctrl .startWatches = []source.TypedSource [reconcile.Request ]{
1246
+ source .Func (func (ctx context.Context , _ workqueue.TypedRateLimitingInterface [reconcile.Request ]) error {
1247
+ return nil
1248
+ }),
1249
+ }
1250
+
1251
+ var wg sync.WaitGroup
1252
+ for i := 0 ; i < 5 ; i ++ {
1253
+ wg .Add (1 )
1254
+ go func () {
1255
+ defer GinkgoRecover ()
1256
+ defer wg .Done ()
1257
+ Expect (ctrl .Warmup (ctx )).To (Succeed ())
1258
+ }()
1259
+ }
1260
+
1261
+ wg .Wait ()
1262
+ })
1263
+
1239
1264
It ("should not race with Start and only start sources once" , func () {
1240
1265
ctx , cancel := context .WithCancel (context .Background ())
1241
1266
defer cancel ()
0 commit comments