Don't replace the global uncaught exception handler during container startup#11920
Open
Develop-KIM wants to merge 1 commit into
Open
Don't replace the global uncaught exception handler during container startup#11920Develop-KIM wants to merge 1 commit into
Develop-KIM wants to merge 1 commit into
Conversation
…startup Testcontainers uses Awaitility in a few core code paths (Docker client discovery, image pulling and the host-port wait strategy). By default Awaitility installs a global default uncaught exception handler through Thread.setDefaultUncaughtExceptionHandler for the duration of each await and restores it afterwards. As a result, simply starting a container temporarily replaces the caller's default handler and can intercept uncaught exceptions thrown by unrelated threads during that window. Opt out of that behaviour with dontCatchUncaughtExceptions() so Testcontainers no longer mutates this JVM-global state. See testcontainers#11483 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #11483
Problem
Testcontainers uses (shaded) Awaitility in a few core paths that run on every container startup:
DockerClientProviderStrategy#test– Docker client discoveryRemoteDockerImage– image pullHostPortWaitStrategy– host-port waitBy default Awaitility installs a global default uncaught exception handler via
Thread.setDefaultUncaughtExceptionHandler(...)for the duration of eachawait()and restores the previous one afterwards. So just starting a container temporarily replaces the caller's default handler, and during that window uncaught exceptions thrown by unrelated application threads are intercepted by Awaitility instead of reaching the application's handler.The stack trace in the issue is exactly this path:
Fix
Add
.dontCatchUncaughtExceptions()to the three coreAwaitility.await()chains, so Testcontainers no longer mutates this JVM-global state. The awaited conditions run in the awaiting / same thread (pollInSameThread), so there is no separate thread whose uncaught exceptions Awaitility would need to catch here.Verification
DockerClientProviderStrategyUncaughtExceptionHandlerTest) that installs a sentinel default handler, drivesDockerClientProviderStrategy#testagainst a closed port, and asserts the global handler is never replaced. Because Awaitility restores the handler once the await finishes, the check has to observe during the await, so it uses a small watcher thread. The test fails onmainand passes with this change.main, and left untouched with this change.This change was drafted with AI assistance (Claude); I reviewed and verified it end-to-end and can speak to every line.