Swallowed Interrupt Signal
ID |
java.interrupt_state_swallowed |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Java |
Tags |
reliability |
Description
Reports a catch clause for InterruptedException or ThreadDeath — including as one arm of a
multi-catch — whose body neither rethrows nor calls Thread.currentThread().interrupt().
Logging the exception is not enough on its own: a body that only logs is reported the same way
as an empty one. Any throw statement in the body satisfies the rule, whether it rethrows the
caught instance or wraps it in a new exception. Only these two exact types are matched by their
simple name — a catch of a broader type such as Exception is out of scope.
A call to a helper that never returns counts as a throw. Agrona’s LangUtil.rethrowUnchecked(e),
Guava’s Throwables.propagate(e) and JUnit’s fail(…) all end the catch body just as a throw
statement does, so a catch that terminates through one is not swallowing anything. They are
recognised by name, from the configurable throwingCalls list.
Configuration
| Property | Default | Description |
|---|---|---|
|
|
Helpers that never return. Matched against the call name alone, or against |
Rationale
Both exceptions carry information the JVM would otherwise lose the moment the catch block
returns normally: that this thread was asked to stop. A handler that only logs and moves on
throws that signal away — the thread keeps running as if nothing happened, so a task the caller
believed was cancelled keeps executing, and the next check for cancellation never sees that it
should have stopped.
try {
process(queue.take());
} catch (InterruptedException e) {
LOGGER.warn("Interrupted!", e); // the interrupt is gone once this returns
}
Remediation
Either restore the interrupt flag before returning, or propagate the exception:
try {
process(queue.take());
} catch (InterruptedException e) {
LOGGER.warn("Interrupted!", e);
Thread.currentThread().interrupt(); // restore the signal for the next check
}