Versions Compared

Key

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

Wiki MarkupAccording to the Java API interface {{Programs may submit only tasks that support interruption using Thread.interrupt() to thread pools that require the ability to shut down the thread pool or to cancel individual tasks within the pool. 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}}, method {{.shutdownNow()}} documentation \[[API 06|AA. Java References#API 06]\]: 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.

...

.

Noncompliant Code Example (

...

Shutting Down Thread Pools)

This noncompliant code example uses submits the SocketReader class defined earlier in the Compliant Solution (close socket connection) of the guideline CON26-J. Ensure that threads and tasks performing blocking operations can be terminated and submits it as a task to a the thread pool defined declared in class 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();
  }
}

public final class SocketReader implements Runnable {
  private final Socket socket;
  // ...
}

The shutdownNow() method may fail to shut down the thread pool because the task lacks support for interruption using the Thread.interrupt() method and because the shutdown() method must wait Because the task does not support interruption through the use of Thread.interrupted(), there is no guarantee that the shutdownNow() method will quiickly shutdown the thread pool. Using the shutdown() method does not fix the problem either, because it waits until all executing tasks have finished.

Similarly, tasks that use some mechanism other than Thread.interrupted() to determine when to shutdown 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 guideline CON24 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 submits the defines an interruptible version of SocketReader discussed in the Compliant Solution (interruptible channel) of the guideline CON26-J. Ensure that threads and tasks performing blocking operations can be terminated, the SocketReader class, which is instantiated and submitted to the thread pool. :

Code Block
bgColor#ccccff

public final class PoolService {
   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);
          // ...
        }

public final class SocketReader implements Runnable      }
    } catch (IOException ie) {
  private    // Forward to handler
    }
  }
}

public final SocketChannel sc;class PoolService {
  // ...
}

Exceptions

EX1: Tasks TPS02-J-EX0: Short-running tasks that execute without blocking may violate this guidelineare exempt from this rule.

Risk Assessment

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

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

CON31TPS02-J

low Low

probable Probable

medium 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

Bibliography

[API 2014]

Interface ExecutorService

[Goetz 2006a]

Chapter 7, "Cancellation and Shutdown"

 

...

Image Added Image Added Image AddedCON30-J. Do not execute interdependent tasks in a bounded thread pool      11. Concurrency (CON)      CON32-J. Ensure that tasks executing in a thread pool do not fail silently