Programs may submit only tasks that support interruption using {{ Wiki Markup Thread.interrupt()
}} to thread pools that require the ability to shut down the thread pool or to cancel individual tasks within the pool. Submitting tasks that lack interruption support to such thread pools is forbidden. According to the Java API interface \[[API 2006|AA. Bibliography#API 06]\], the {{Programs must not submit tasks that lack interruption support to such thread pools. According to the Java API [API 2014], the java.util.concurrent.ExecutorService.shutdownNow()
}} method
Attempts attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution....
There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via
Thread.interrupt()
, so any task that fails to respond to interrupts may never terminate.
Similarly, when attempting to cancel individual tasks within the thread pool using the Future.cancel()
method, ensure that the tasks support interruption.
Noncompliant Code Example (Shutting Down Thread Pools)
This noncompliant code example submits the SocketReader
class as a task to the thread pool declared in PoolService
.:
Code Block | ||
---|---|---|
| ||
public final class SocketReader implements Runnable { // Thread-safe class private final Socket socket; private final BufferedReader in; private final Object lock = new Object(); public SocketReader(String host, int port) throws IOException { this.socket = new Socket(host, port); this.in = new BufferedReader( new InputStreamReader(this.socket.getInputStream()) ); } // Only one thread can use the socket at a particular time @Override public void run() { try { synchronized (lock) { readData(); } } catch (IOException ie) { // Forward to handler } } public void readData() throws IOException { String string; try { while ((string = in.readLine()) != null) { // Blocks until end of stream (null) } } finally { shutdown(); } } public void shutdown() throws IOException { socket.close(); } } public final class PoolService { private final ExecutorService pool; public PoolService(int poolSize) { pool = Executors.newFixedThreadPool(poolSize); } public void doSomething() throws InterruptedException, IOException { pool.submit(new SocketReader("somehost", 8080)); // ... List<Runnable> awaitingTasks = pool.shutdownNow(); } public static void main(String[] args) throws InterruptedException, IOException { PoolService service = new PoolService(5); service.doSomething(); } } |
The shutdownNow()
method may fail to shut down the thread pool because the task lacks support for interruption using the Thread.interrupt()
method . Use of and because the shutdown()
method also fails to fix the problem because it waits must wait until all executing tasks have finished.
Similarly, tasks that use some mechanism other than Thread.interrupted()
to determine when to shut down will be unresponsive to shutdown()
or and shutdownNow()
. For instance, tasks that check a volatile flag to determine whether it is safe to shutdown will be are unresponsive to these methods. The rule THI05-J. Do not use Thread.stop() to terminate threads provides more information on using a flag to terminate threads.
...
This compliant solution defines an interruptible version of the SocketReader
class, which is instantiated and submitted to the thread pool.:
Code Block | ||
---|---|---|
| ||
public final class SocketReader implements Runnable {
private final SocketChannel sc;
private final Object lock = new Object();
public SocketReader(String host, int port) throws IOException {
sc = SocketChannel.open(new InetSocketAddress(host, port));
}
@Override public void run() {
ByteBuffer buf = ByteBuffer.allocate(1024);
try {
synchronized (lock) {
while (!Thread.interrupted()) {
sc.read(buf);
// ...
}
}
} catch (IOException ie) {
// Forward to handler
}
}
}
public final class PoolService {
// ...
}
|
Exceptions
TPS02-J-EX1EX0: Short-running tasks that execute without blocking are exempt from this rule.
...
Submitting tasks that are uninterruptible may prevent a thread pool from shutting down and consequently may cause denial of service DoS.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
TPS02-J | low Low | probable Probable | medium Medium | P4 | L3 |
Related Vulnerabilities
...
Bibliography
...
[[API 2006 | AA. Bibliography#API 06]] | interface ExecutorService | ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="d462d12f-2984-41a5-be6e-4983b96a4052"><ac:plain-text-body><![CDATA[ | [[Goetz 2006 | AA. Bibliography#Goetz 06]] | Chapter 7: Cancellation and shutdown | ]]></ac:plain-text-body></ac:structured-macro> |
Chapter 7, "Cancellation and Shutdown" |
...