Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Replaced 1st NCCE/CS set

...

Threads

...

always

...

preserve

...

class

...

invariants

...

when

...

they

...

are

...

allowed

...

to

...

exit

...

normally.

...

Programmers

...

often

...

try

...

to

...

forcefully

...

terminate

...

threads

...

when

...

they

...

believe

...

that

...

the

...

task

...

is

...

accomplished,

...

the

...

request

...

has

...

been

...

canceled

...

or

...

the

...

program

...

needs

...

to

...

quickly

...

shutdown.

...

A

...

few

...

thread

...

APIs

...

were

...

introduced

...

to

...

facilitate

...

thread

...

suspension,

...

resumption

...

and

...

termination

...

but

...

were

...

later

...

deprecated

...

due

...

to

...

inherent

...

design

...

weaknesses.

...

The

...

Thread.stop()

...

method

...

is

...

one

...

example.

...

It

...

throws

...

a

...

ThreadDeath

...

exception

...

to

...

stop

...

the

...

thread.

...

Two

...

cases

...

arise:

...

  • If ThreadDeath is left uncaught, it allows the execution of a finally block which performs the usual cleanup operations. Use of the Thread.stop()

...

  • method

...

  • is

...

  • highly

...

  • inadvisable

...

  • because

...

  • of

...

  • two

...

  • reasons.

...

  • First,

...

  • no

...

  • particular

...

  • thread

...

  • can

...

  • be

...

  • forcefully

...

  • stopped

...

  • because

...

  • an

...

  • arbitrary

...

  • thread

...

  • can

...

  • catch

...

  • the

...

  • thrown

...

  • ThreadDeath

...

  • exception

...

  • and

...

  • simply

...

  • choose

...

  • to

...

  • ignore

...

  • it.

...

  • Second,

...

  • stopping

...

  • threads

...

  • abruptly

...

  • results

...

  • in

...

  • the

...

  • release

...

  • of

...

  • all

...

  • the

...

  • associated

...

  • monitors,

...

  • violating

...

  • the

...

  • guarantees

...

  • provided

...

  • by

...

  • the

...

  • critical

...

  • sections.

...

  • Moreover,

...

  • the

...

  • objects

...

  • end

...

  • up

...

  • in

...

  • an

...

  • inconsistent

...

  • state,

...

  • nondeterministic

...

  • behavior

...

  • being

...

  • a

...

  • typical

...

  • outcome.

...

  • As a remediation measure,

...

  • catching

...

  • the

...

  • ThreadDeath

...

  • exception

...

  • on

...

  • the

...

  • other

...

  • hand

...

  • can

...

  • itself

...

  • ensnarl

...

  • multithreaded

...

  • code.

...

  • For

...

  • one,

...

  • the

...

  • exception

...

  • can

...

  • be

...

  • thrown

...

  • anywhere,

...

  • making

...

  • it

...

  • difficult

...

  • to

...

  • trace

...

  • and

...

  • effectively

...

  • recover

...

  • from

...

  • the

...

  • exceptional

...

  • condition.

...

  • Also,

...

  • there

...

  • is

...

  • nothing

...

  • stopping

...

  • a

...

  • thread

...

  • from

...

  • throwing

...

  • another

...

  • ThreadDeath

...

  • exception

...

  • while

...

  • recovery

...

  • is

...

  • in

...

  • progress.

...

Noncompliant Code Example (Deprecated Thread.stop()

...

)

...

This

...

noncompliant

...

code

...

example

...

shows

...

a

...

thread that fills a vector with strings. The thread is shut down after a fixed period of time time.

Code Block
bgColor#FFcccc

public class Container implements Runnable {
  private final Vector<String> vector = new Vector<String>();
  public Vector<String> getVector() {
    return vector;
  }
  
  public void run() {
    String string = null;
    do {
      System.out.println("Enter another string");
      BufferedReader in = new BufferedReader(new InputStreamReader(System.in) that forcefully comes to a halt when the {{Thread.stop()}} method is invoked. Neither the {{catch}} nor the {{finally}} block executes. Any monitors that are held are immediately released, leaving the object in a delicate state.

{mc} Try to retain the debug statements in the NCE to illustrate the problem {mc}

{code:bgColor=#FFcccc}
class BadStop implements Runnable {
  public void run() {
    try {
      Thread.currentThread().sleep(1000);
    } catch(InterruptedException ie)try { // Not
 executed 
      string = Systemin.out.println("Performing cleanup"readLine();
  
    } finallycatch { // Not executed
(IOException e) {
         System.out.println("Closing resources"); // Forward to handler
    }   }
    
  }
}

class Controller {vector.add(string);
    } while (!"END".equals(string));
  }

  public static void main(String[] args) throws InterruptedException {
    ThreadContainer tc = new Container();
    Thread( thread = new BadStopThread()c);
    tthread.start();  
    tThread.interruptsleep(5000); // Artificially induce an InterruptedException
    tthread.stop();      // Force thread cancellation
  }
}

Since vector is thread-safe, it is only accessible to this program while in a consistent state. That is, the Vector.size() method always reflects the true number of elements in the vector. When a new element is added to the vector, it adjusts its internal data and its internal data is temporarily inconsistent. But the vector uses its own intrinsic lock to prevent other threads from accessing it while its state is inconsistent.

Wiki Markup
However, the {{Thread.stop()}} method causes the thread to stop what it is doing and throw a {{ThreadDeath}} object, and also to release all locks \[[API 06|AA. Java References#API 06]\]. If the thread is currently adding a new string to the vector when it gets stopped, then the vector may become visible while in an inconsistent state. This might mean, for instance, that {{Vector.size()}} is 3 while the vector actually only contains 2 elements.

Compliant Solution (volatile flag)

This compliant example stops the thread by making use of a volatile flag. An accessor method shutdown() is used to set the flag to true, after which the thread can start the cancellation process.

Code Block
bgColor#ccccff

public class Container implements Runnable {
  private final Vector<String> vector = new Vector<String>();
  
  private volatile boolean done = false;
  
  public Vector<String> getVector() {
    return vector;
  }
  
  public void shutdown() {
	  done = true;
  }

  public void run() {
    String string = null;
    do {
      System.out.println("Enter another string");
      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
      try {
        string = in.readLine();
      } catch (IOException e) {
        // Forward to handler
      }
      vector.add(string);
    } while (!done && !"END".equals(string));
  }

  public static void main(String[] args) throws InterruptedException {
    Container c = new Container();
    Thread thread = new Thread(c);
    thread.start();
    Thread.sleep(5000);
    c.shutdown();
    return;
  }
}

Compliant Solution (Interruptible)

This compliant example stops the thread by making use of a volatile flag. An accessor method shutdown() is used to set the flag to true, after which the thread can start the cancellation process.

Code Block
bgColor#ccccff

public class Container implements Runnable {
  private final Vector<String> vector = new Vector<String>();
  
  public Vector<String> getVector() {
  	return vector;
  }

  public void run() {
    String string = null;
    do {
      System.out.println("Enter another string");
      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
      try {
        string = in.readLine();
      } catch (IOException e) {
        // Forward to handler
      }
      vector.add(string);
    } while (!Thread.interrupted() && !"END".equals(string));
  }

  public static void main(String[] args) throws InterruptedException {
    Container c = new Container();
    Thread thread = new Thread(c);
    thread.start();
    Thread.sleep(5000);
    thread.interrupt();
  }
}

Compliant Solution (RuntimePermission stopThread)

Remove the default permission java.lang.RuntimePermission stopThread from the security policy file to deny the Thread.stop() invoking code, the required privileges.

Noncompliant Code Example (blocking IO)

This noncompliant code example uses the advice suggested in the previous compliant solution. However, this does not help in terminating the thread because it is blocked on some network IO as a consequence of using the readLine() method.

Code Block
bgColor#FFcccc
{code}

The {{Thread.interrupt()}} method is frequently used to awaken a blocked thread before it can be stopped. It awakens threads that are blocked on {{wait()}} methods of class {{Object}}, and {{join}} and {{sleep}} methods of class {{Thread}}. In these cases, the thread's interrupt status is cleared and it receives an {{InterruptedException}}. If the thread is blocked on I/O operations upon an interruptible channel, the channel is closed, the thread's interrupt status is set and it receives a {{ClosedByInterruptException}}. Similarly, a thread waiting on a selector also returns from the operation with its interrupted status set. \[[API 06|AA. Java References#API 06]\]   

The {{java.lang.ThreadGroup.interrupt()}} is not deprecated and is often seen as an option to interrupt all the threads belonging to a thread group. "This is no guarantee that a program will terminate, however, because libraries that you have used may have created user threads that do not respond to interrupt requests. The AWT graphics library is one well-known example." \[[JPL 06|AA. Java References#JPL 06]\]. Moreover, using the {{ThreadGroup}} API is discouraged (see [CON17-J. Avoid using ThreadGroup APIs]).

h2. Compliant Solution (1) ({{volatile}} flag)

This compliant example uses a {{boolean}} flag called {{done}} to indicate whether the thread should be stopped after any necessary cleanup code has finished executing. An accessor method {{shutdown()}} is used to set the flag to {{true}}, after which the thread can start the cancellation process. The {{done}} flag is also set immediately after the execution of the {{finally}} block's resource clean-up statements so that the system does not continue relinquishing resources that it has already released, in the event of the {{done}} flag staying {{false}}.

{code:bgColor=#ccccff}
class ControlledStop implements Runnable{
  protected volatile boolean done = false;
  public void run() {
    while(!done) {
      try {
        Thread.currentThread().sleep(1000);
      } catch(InterruptedException ie) { 
          // Handle the exception 
      } finally { 
          done = true;
      }
    } 
    done = false; // Reset for later use
    System.out.println("Done!");
  }

  protected void shutdown(){
    done = true;
  }
}

class Controller {
  public static void main(String[] args) throws InterruptedException {  
    ControlledStop c = new ControlledStop();
    Thread t = new Thread(c);
    t.start();
    t.interrupt();       // Artificially induce an InterruptedException
    Thread.sleep(1000);  // Wait for some time to allow the exception
                         // to be caught (demonstration only)
    c.shutdown();
  }
}
{code} 

h2. Compliant Solution (2) ({{RuntimePermission stopThread}})

Remove the default permission {{java.lang.RuntimePermission}} {{stopThread}} from the security policy file to deny the {{Thread.stop()}} invoking code, the required privileges. 

h2. Noncompliant Code Example (blocking IO)

This noncompliant code example uses the advice suggested in the previous compliant solution. However, this does not help in terminating the thread because it is blocked on some network IO as a consequence of using the {{readLine()}} method.

{code:bgColor=#FFcccc}
class StopSocket extends Thread {
  private Socket s;
  private volatile boolean done = false;
  
  public void run() { 
    while(!done) {
      try {
        s = new Socket("somehost", 25);
        BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        String s = null;
        while((s = br.readLine()) != null) { 
          // Blocks until end of stream (null)
        }
      } catch (IOException ie) { 
          // Forward to handler
      } finally {
          done = true;
      }
    }
  }  

  public void shutdown() throws IOException {
    done = true;
  }
}

class Controller {
  public static void main(String[] args) throws InterruptedException, IOException {
     StopSocket ss = new StopSocket();
     Thread t = new Thread(ss);
     t.start();
     Thread.sleep(1000); 
     ss.shutdown();
  }
}
{code}

A {{Socket}} connection is not affected by the {{InterruptedException}} that results with the use of the {{

A Socket connection is not affected by the InterruptedException that results with the use of the Thread.interrupt()

...

method.

...

The

...

boolean

...

flag

...

solution

...

does

...

not

...

work

...

in

...

such

...

cases.

...

Compliant

...

Solution

...

(close

...

socket

...

connection)

...

This

...

compliant

...

solution

...

closes

...

the

...

socket

...

connection,

...

both

...

using

...

the

...

shutdown()

...

method

...

as

...

well

...

as

...

the

...

finally

...

block.

...

As

...

a

...

result,

...

the

...

thread

...

is

...

bound

...

to

...

stop

...

due

...

to

...

a

...

SocketException

...

.

...

Note

...

that

...

there

...

is

...

no

...

way

...

to

...

keep

...

the

...

connection

...

alive

...

if

...

the

...

thread

...

is

...

to

...

be

...

cleanly

...

halted

...

immediately.

Code Block
bgColor#ccccff


{code:bgColor=#ccccff}
class StopSocket extends Thread {
  private Socket s;
 
  public void run() { 
    try {
      s = new Socket("somehost", 25);
      BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
      String s = null;
      while((s = br.readLine()) != null) { 
        // Blocks until end of stream (null)
      }
    } catch (IOException ie) { 
        // Handle the exception 
    } finally {
        try {
          if(s != null)
            s.close();
        } catch (IOException e) { /* Forward to handler */ }
    }
  }

  public void shutdown() throws IOException {
    if(s != null)
      s.close();
  }
}

class Controller {
  public static void main(String[] args) throws InterruptedException, IOException {
    StopSocket ss = new StopSocket();
    Thread t = new Thread(ss);
    t.start();
    Thread.sleep(1000); 
    ss.shutdown();
  }
}
{code}

A {{boolean}} flag can be used (as described earlier) if additional 

A boolean flag can be used (as described earlier) if additional clean-up operations need to be performed.

Compliant Solution (2) (interruptible channel)

This compliant solution uses an interruptible channel, SocketChannel instead of a Socket connection. If the thread performing the network IO is interrupted using the Thread.interrupt() method, for instance, while reading the data, the thread receives a ClosedByInterruptException and the channel is closed immediately. The thread's interrupt status is also set.

Code Block
bgColor#ccccff
clean-up operations need to be performed.

h2. Compliant Solution (2) (interruptible channel)

This compliant solution uses an interruptible channel, {{SocketChannel}} instead of a {{Socket}} connection. If the thread performing the network IO is interrupted using the {{Thread.interrupt()}} method, for instance, while reading the data, the thread receives a {{ClosedByInterruptException}} and the channel is closed immediately. The thread's interrupt status is also set.

{code:bgColor=#ccccff}
class StopSocket extends Thread {
  private volatile boolean done = false;
  public void run() { 
    while(!done) {
      try {
    	InetSocketAddress addr = new InetSocketAddress("somehost", 25);
        SocketChannel sc = SocketChannel.open(addr);
        ByteBuffer buf = ByteBuffer.allocate(1024);
        sc.read(buf);
        // ...
      } catch (IOException ie) {  
          // Handle the exception
      } finally {
          done = true;
      }
    }
  }  

  public void shutdown() throws IOException {
    done = true;
  }
}
{code}

h2. Risk Assessment

Trying to force thread shutdown can result in inconsistent object state and corrupt the object. Critical resources may also leak if cleanup operations are not carried out as required.

|| Rule || Severity || Likelihood || Remediation Cost || Priority || Level ||
| CON13- J | low | probable | medium | {color:green}{*}P4{*}{color} | {color:green}{*}L3{*}{color} |



h3. Automated Detection

TODO



h3. Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the [CERT website|https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+CON35-J].

h2. References

\[[API 06|AA. Java References#API 06]\] Class Thread, method {{stop}}
\[[Darwin 04|AA. Java References#Darwin 04]\] 24.3 Stopping a Thread
\[[JDK7 08|AA. Java References#JDK7 08]\] Concurrency Utilities, More information: Java Thread Primitive Deprecation 
\[[JPL

Risk Assessment

Trying to force thread shutdown can result in inconsistent object state and corrupt the object. Critical resources may also leak if cleanup operations are not carried out as required.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

CON13- 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]\] 

...

Class Thread, method {{stop}}
\[[

...

Darwin 04|AA. Java 

...

References#Darwin 04]\] 

...

24.3 Stopping a Thread

...

\[[JDK7 08|AA. Java References#JDK7 08]\] Concurrency Utilities, More information: Java Thread Primitive Deprecation 
\[[JPL 06|AA. Java References#JPL 06]\] 14.12.1. Don't stop and 23.3.3. Shutdown Strategies
\[[JavaThreads 04|AA. Java References#JavaThreads 04]\] 2.4 Two Approaches to Stopping a Thread

...

CON12-J. Avoid deadlock by requesting and releasing locks in the same order      11. Concurrency (CON)      VOID CON14-J. Ensure atomicity of 64-bit operations