Skip to content

Fix race condition in reflectorRunOnce test between list completion and watch start#4632

Merged
brendandburns merged 4 commits intodependabot/maven/org.apache.felix-maven-bundle-plugin-6.0.2from
copilot/sub-pr-4630
Mar 3, 2026
Merged

Fix race condition in reflectorRunOnce test between list completion and watch start#4632
brendandburns merged 4 commits intodependabot/maven/org.apache.felix-maven-bundle-plugin-6.0.2from
copilot/sub-pr-4630

Conversation

Copy link
Contributor

Copilot AI commented Mar 3, 2026

  • Identify the race condition: reflectorRunOnce test waited for lastSyncResourceVersion (set before watch starts), allowing stop() to be called before watch() was invoked; Awaitility.await().forever() doesn't actually block without .until()
  • Fix reflectorRunOnce to use a CountDownLatch that signals when watch() is actually called, ensuring stop() is only called after the watch has started
  • Re-add the mockResourceVersion assertion (assertThat(reflectorRunnable.getLastSyncResourceVersion()).isEqualTo(mockResourceVersion)) that was accidentally removed
  • Replace Thread.sleep(1 hour) with a second CountDownLatch (watchCanReturnLatch): watch() mock awaits this latch; finally block calls stop() first then counts down the latch, ensuring the reflector sees isActive=false when watch() returns
  • Verify tests pass reliably (5 consecutive runs, 12 tests each)

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@k8s-ci-robot k8s-ci-robot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 3, 2026
@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/XS Denotes a PR that changes 0-9 lines, ignoring generated files. labels Mar 3, 2026
…stopping

Co-authored-by: brendandburns <5751682+brendandburns@users.noreply.github.com>
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Copilot
Once this PR has been reviewed and has the lgtm label, please ask for approval from brendandburns. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added size/S Denotes a PR that changes 10-29 lines, ignoring generated files. and removed size/XS Denotes a PR that changes 0-9 lines, ignoring generated files. labels Mar 3, 2026
Copilot AI changed the title [WIP] Build(deps): bump org.apache.felix:maven-bundle-plugin to 6.0.2 Fix race condition in reflectorRunOnce test between list completion and watch start Mar 3, 2026
@brendandburns
Copy link
Contributor

@copilot looks like you removed validation that the mockResourceVersion was set, and also I'm not sure the Thread.sleep() is required.

Co-authored-by: brendandburns <5751682+brendandburns@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 3, 2026

@copilot looks like you removed validation that the mockResourceVersion was set, and also I'm not sure the Thread.sleep() is required.

Addressed in 373ebe0. Re-added assertThat(reflectorRunnable.getLastSyncResourceVersion()).isEqualTo(mockResourceVersion) after stop() returns.

On Thread.sleep(): it is required for two reasons. First, returning null from watch() without it causes a NullPointerException at newWatch.close() in the synchronized block (line 132 of ReflectorRunnable.run()). Second, returning an empty MockWatch without it causes the reflector to loop and call watch() a second time before stop() is effective, breaking verify(times(1)).watch(any()).

@brendandburns
Copy link
Contributor

@copilot I don't like that we're just hanging this thread. I think that this is just a hacky way to make sure that the watch is ongoing before we call stop. Maybe we should just add a second countdown latch that waits until stop is called before counting down.

Co-authored-by: brendandburns <5751682+brendandburns@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 3, 2026

@copilot I don't like that we're just hanging this thread. I think that this is just a hacky way to make sure that the watch is ongoing before we call stop. Maybe we should just add ...

Done in e52c5a4. Replaced Thread.sleep with a second CountDownLatch (watchCanReturnLatch). The watch() mock counts down watchCalledLatch when invoked, then awaits watchCanReturnLatch before returning a MockWatch. In the finally block, stop() is called first (sets isActive=false) and then watchCanReturnLatch.countDown() releases the mock — so the reflector always sees isActive=false when watch() returns and exits cleanly.

@brendandburns brendandburns marked this pull request as ready for review March 3, 2026 20:19
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 3, 2026
@brendandburns brendandburns merged commit 505d9fc into dependabot/maven/org.apache.felix-maven-bundle-plugin-6.0.2 Mar 3, 2026
1 of 2 checks passed
@k8s-ci-robot k8s-ci-robot requested a review from yue9944882 March 3, 2026 20:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/S Denotes a PR that changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants