Skip to content

Commit 1a13241

Browse files
barchettatjquinno
andauthored
4.x fix status from deadlock health check if invoking the MBean fails (#9694) (#9764)
* Report ERROR instead of DOWN if MBean invocation fails * Fix confusing comment Co-authored-by: Tim Quinn <[email protected]>
1 parent 12a1d97 commit 1a13241

File tree

2 files changed

+24
-9
lines changed

2 files changed

+24
-9
lines changed

health/health-checks/src/main/java/io/helidon/health/checks/DeadlockHealthCheck.java

+14-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2023 Oracle and/or its affiliates.
2+
* Copyright (c) 2018, 2025 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
1919
import java.lang.System.Logger.Level;
2020
import java.lang.management.ManagementFactory;
2121
import java.lang.management.ThreadMXBean;
22+
import java.util.Arrays;
2223

2324
import io.helidon.common.NativeImageHelper;
2425
import io.helidon.health.HealthCheck;
@@ -95,17 +96,22 @@ public HealthCheckResponse call() {
9596
.build();
9697
}
9798

98-
boolean noDeadLock = false;
99+
HealthCheckResponse.Builder builder = HealthCheckResponse.builder();
100+
99101
try {
100102
// Thanks to https://stackoverflow.com/questions/1102359/programmatic-deadlock-detection-in-java#1102410
101-
noDeadLock = (threadBean.findDeadlockedThreads() == null);
103+
long[] deadlockedThreads = threadBean.findDeadlockedThreads();
104+
if (deadlockedThreads != null) {
105+
builder.status(Status.DOWN);
106+
LOGGER.log(Level.TRACE, "Health check observed deadlocked threads: " + Arrays.toString(deadlockedThreads));
107+
}
102108
} catch (Throwable e) {
103-
// ThreadBean does not work - probably in native image
104-
LOGGER.log(Level.TRACE, "Failed to find deadlocks in ThreadMXBean, ignoring this healthcheck", e);
109+
// ThreadBean does not work - probably in native image. Report ERROR, not DOWN, because we do not know that
110+
// there are deadlocks which DOWN should imply; we simply cannot find out.
111+
LOGGER.log(Level.TRACE, "Error invoking ThreadMXBean to find deadlocks; cannot complete this healthcheck", e);
112+
builder.status(Status.ERROR);
105113
}
106-
return HealthCheckResponse.builder()
107-
.status(noDeadLock ? Status.UP : Status.DOWN)
108-
.build();
114+
return builder.build();
109115
}
110116
}
111117

health/health-checks/src/test/java/io/helidon/health/checks/DeadlockHealthCheckTest.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2022 Oracle and/or its affiliates.
2+
* Copyright (c) 2018, 2025 Oracle and/or its affiliates.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -63,4 +63,13 @@ void noDeadlockDetected() {
6363
HealthCheckResponse response = check.call();
6464
assertThat(response.status(), is(HealthCheckResponse.Status.UP));
6565
}
66+
67+
@Test
68+
69+
void errorInvokingMBean() {
70+
Mockito.when(threadBean.findDeadlockedThreads()).thenThrow(new RuntimeException("Simulated error invoking MBean"));
71+
DeadlockHealthCheck check = new DeadlockHealthCheck(threadBean);
72+
HealthCheckResponse response = check.call();
73+
assertThat(response.status(), is(HealthCheckResponse.Status.ERROR));
74+
}
6675
}

0 commit comments

Comments
 (0)