Skip to content

Commit c8721a4

Browse files
committed
Disable Awaitility uncaught-exception catching (fixes #11483)
1 parent 43c6a97 commit c8721a4

File tree

6 files changed

+99
-0
lines changed

6 files changed

+99
-0
lines changed

core/src/main/java/org/testcontainers/containers/GenericContainer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,7 @@ private void tryStart() {
447447
// Wait until inspect container returns the mapped ports
448448
containerInfo =
449449
await()
450+
.dontCatchUncaughtExceptions()
450451
.atMost(5, TimeUnit.SECONDS)
451452
.pollInterval(DynamicPollInterval.ofMillis(50))
452453
.pollInSameThread()

core/src/main/java/org/testcontainers/containers/wait/strategy/HostPortWaitStrategy.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ protected void waitUntilReady() {
8282
Instant now = Instant.now();
8383
Awaitility
8484
.await()
85+
.dontCatchUncaughtExceptions()
8586
.pollInSameThread()
8687
.pollInterval(Duration.ofMillis(100))
8788
.pollDelay(Duration.ZERO)

core/src/main/java/org/testcontainers/dockerclient/DockerClientProviderStrategy.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ protected boolean test() {
208208
try (Socket socket = socketProvider.call()) {
209209
Awaitility
210210
.await()
211+
.dontCatchUncaughtExceptions()
211212
.atMost(TestcontainersConfiguration.getInstance().getClientPingTimeout(), TimeUnit.SECONDS) // timeout after configured duration
212213
.pollInterval(Duration.ofMillis(200)) // check state every 200ms
213214
.pollDelay(Duration.ofSeconds(0)) // start checking immediately

core/src/main/java/org/testcontainers/images/RemoteDockerImage.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ protected final String resolve() {
102102

103103
Awaitility
104104
.await()
105+
.dontCatchUncaughtExceptions()
105106
.pollInSameThread()
106107
.pollDelay(Duration.ZERO) // start checking immediately
107108
.atMost(PULL_RETRY_TIME_LIMIT)
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package org.testcontainers.utility;
2+
3+
import org.junit.jupiter.api.Test;
4+
import org.awaitility.Awaitility;
5+
6+
import java.io.InputStream;
7+
import java.nio.charset.StandardCharsets;
8+
import java.time.Duration;
9+
import java.util.concurrent.CountDownLatch;
10+
import java.util.concurrent.TimeUnit;
11+
import java.util.concurrent.atomic.AtomicBoolean;
12+
import java.util.concurrent.atomic.AtomicReference;
13+
import java.util.concurrent.locks.LockSupport;
14+
15+
import static org.assertj.core.api.Assertions.assertThat;
16+
17+
class DockerClientProviderStrategyUncaughtExceptionHandlerTest {
18+
19+
@Test
20+
void dockerClientProviderStrategyTestShouldUseDontCatchUncaughtExceptions() throws Exception {
21+
byte[] bytes;
22+
try (InputStream is = getClass()
23+
.getClassLoader()
24+
.getResourceAsStream("org/testcontainers/dockerclient/DockerClientProviderStrategy.class")) {
25+
assertThat(is).isNotNull();
26+
bytes = is.readAllBytes();
27+
}
28+
29+
// Use ISO_8859_1 to preserve a stable 1:1 mapping of bytes to chars for a lightweight constant-pool substring check.
30+
String content = new String(bytes, StandardCharsets.ISO_8859_1);
31+
assertThat(content).contains("dontCatchUncaughtExceptions");
32+
}
33+
34+
@Test
35+
void shouldNotInterceptUncaughtExceptionsFromOtherThreads() throws Exception {
36+
Thread.UncaughtExceptionHandler originalHandler = Thread.getDefaultUncaughtExceptionHandler();
37+
AtomicReference<Throwable> observedException = new AtomicReference<>();
38+
CountDownLatch observedExceptionLatch = new CountDownLatch(1);
39+
Thread.UncaughtExceptionHandler expectedHandler = (t, e) -> {
40+
if (observedException.compareAndSet(null, e)) {
41+
observedExceptionLatch.countDown();
42+
}
43+
};
44+
45+
Thread.setDefaultUncaughtExceptionHandler(expectedHandler);
46+
try {
47+
AtomicReference<Thread.UncaughtExceptionHandler> changedHandler = new AtomicReference<>();
48+
AtomicBoolean monitorStop = new AtomicBoolean(false);
49+
Thread monitor = new Thread(() -> {
50+
while (!monitorStop.get()) {
51+
Thread.UncaughtExceptionHandler current = Thread.getDefaultUncaughtExceptionHandler();
52+
if (current != expectedHandler) {
53+
changedHandler.compareAndSet(null, current);
54+
break;
55+
}
56+
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(1));
57+
}
58+
}, "docker-strategy-uncaught-handler-monitor");
59+
60+
Thread thrower = new Thread(() -> {
61+
try {
62+
Thread.sleep(100);
63+
} catch (InterruptedException ignored) {
64+
return;
65+
}
66+
throw new RuntimeException("boom");
67+
}, "docker-strategy-uncaught-handler-thrower");
68+
69+
monitor.start();
70+
thrower.start();
71+
72+
Awaitility
73+
.await()
74+
.dontCatchUncaughtExceptions()
75+
.pollDelay(Duration.ZERO)
76+
.pollInterval(Duration.ofMillis(25))
77+
.atMost(Duration.ofSeconds(2))
78+
.until(() -> {
79+
Thread.sleep(300);
80+
return true;
81+
});
82+
83+
monitorStop.set(true);
84+
monitor.join(TimeUnit.SECONDS.toMillis(5));
85+
thrower.join(TimeUnit.SECONDS.toMillis(5));
86+
87+
assertThat(changedHandler.get()).isNull();
88+
assertThat(observedExceptionLatch.await(5, TimeUnit.SECONDS)).isTrue();
89+
assertThat(observedException.get()).isInstanceOf(RuntimeException.class).hasMessage("boom");
90+
} finally {
91+
Thread.setDefaultUncaughtExceptionHandler(originalHandler);
92+
}
93+
}
94+
}

modules/solace/src/main/java/org/testcontainers/solace/SolaceContainer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ private void updateConfigScript(StringBuilder scriptBuilder, String command) {
222222
private void waitOnCommandResult(String waitingFor, String... command) {
223223
Awaitility
224224
.await()
225+
.dontCatchUncaughtExceptions()
225226
.pollInterval(Duration.ofMillis(500))
226227
.timeout(Duration.ofSeconds(30))
227228
.until(() -> {

0 commit comments

Comments
 (0)