Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

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
bgColor#FFcccc
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();
  }
}

...

Similarly, tasks that use some mechanism other than Thread.interrupted() to determine when to shutdown will be unresponsive to shutdown() or shutdownNow(). For instance, tasks that check a volatile flag to determine whether it is safe to shutdown will be unresponsive to these methods. The guideline THI05-J. Do not use Thread.stop() to terminate threads provides more information on using a flag to terminate threads.

Compliant Solution (Submit Interruptible Tasks)

This compliant solution defines an interruptible version of the SocketReader class, which is instantiated and submitted to the thread pool.

Code Block
bgColor#ccccff
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

CON31-EX1: Short-running tasks that execute without blocking are not required to adhere to this guideline.

Risk Assessment

Submitting tasks that are not interruptible may preclude the thread pool from shutting down and cause denial of service.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

CON31- J

low

probable

medium

P4

L3

Automated Detection

TODO

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

Wiki Markup
\[[API 06|AA. Java References#API 06]\] interface ExecutorService
\[[Goetz 06|AA. Java References#Goetz 06]\] Chapter 7: Cancellation and shutdown

...