Java Should There Be Just One Thread to Read From Socket

Threads and tasks that block on operations involving network or file I/O must provide callers with an explicit termination mechanism to prevent denial-of-service (DoS) vulnerabilities.

Noncompliant Code Example (Blocking I/O, Volatile Flag)

This noncompliant lawmaking case uses a volatile done flag to point it whether is rubber to shut down the thread, as suggested in THI05-J. Do not use Thread.stop() to end threads. However, when the thread is blocked on network I/O as a upshot of invoking the readLine() method, it cannot respond to the newly gear up flag until the network I/O is complete. Consequently, thread termination may exist indefinitely delayed.

// Thread-safe class  public final form SocketReader implements Runnable {    private last Socket socket;   individual final BufferedReader in;   private volatile boolean done = false;   private final Object lock = new Object();    public SocketReader(Cord 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 item time   @Override public void run() {     try {       synchronized (lock) {         readData();       }     } catch (IOException ie) {       // Frontwards to handler     }   }    public void readData() throws IOException {     String string;     while (!done && (string = in.readLine()) != nada) {       // Blocks until terminate of stream (null)     }   }    public void shutdown() {     done = true;   }    public static void main(String[] args)                            throws IOException, InterruptedException {     SocketReader reader = new SocketReader("somehost", 25);     Thread thread = new Thread(reader);     thread.start();     Thread.sleep(1000);     reader.shutdown(); // Close downwards the thread   } }          

Noncompliant Lawmaking Example (Blocking I/O, Interruptible)

This noncompliant code example is like to the preceding instance but uses thread suspension to close down the thread. Network I/O on a java.net.Socket is unresponsive to thread intermission.

// Thread-rubber course  public final form SocketReader implements Runnable {    // Other methods...    public void readData() throws IOException {     String string;     while (!Thread.interrupted() && (cord = in.readLine()) != cipher) {       // Blocks until cease of stream (zero)     }   }    public static void main(Cord[] args)                            throws IOException, InterruptedException {     SocketReader reader = new SocketReader("somehost", 25);     Thread thread = new Thread(reader);     thread.start();     Thread.sleep(g);     thread.interrupt(); // Interrupt the thread   } }          

Compliant Solution (Close Socket Connection)

This compliant solution terminates the blocking network I/O by closing the socket in the shutdown() method. The readLine() method throws a SocketException when the socket is closed, consequently allowing the thread to proceed. Note that it is incommunicable to keep the connection alive while simultaneously halting the thread both cleanly and immediately.

public final course SocketReader implements Runnable {   // Other methods...    public void readData() throws IOException {     String cord;     endeavour {       while ((string = in.readLine()) != cypher) {         // Blocks until end of stream (null)       }     } finally {       shutdown();     }   }    public void shutdown() throws IOException {     socket.close();   }    public static void main(String[] args)                            throws IOException, InterruptedException {     SocketReader reader = new SocketReader("somehost", 25);     Thread thread = new Thread(reader);     thread.start();     Thread.sleep(k);     reader.shutdown();   } }          

After the shutdown() method is called from chief(), the finally block in readData() executes and calls shutdown() again, closing the socket for a second time. Notwithstanding, when the socket has already been closed, this second phone call does nil.

When performing asynchronous I/O, a coffee.nio.channels.Selector can be unblocked past invoking either its close() or its wakeup() method.

When additional operations must be performed after emerging from the blocked state, apply a boolean flag to indicate pending termination. When supplementing the lawmaking with such a flag, the shutdown() method should also set the flag to simulated then that the thread can cleanly exit from the while loop.

Compliant Solution (Interruptible Aqueduct)

This compliant solution uses an interruptible channel, java.nio.channels.SocketChannel, instead of a Socket connection. If the thread performing the network I/O is interrupted using the Thread.interrupt() method while it is reading the information, the thread receives a ClosedByInterruptException, and the aqueduct is closed immediately. The thread'due south interrupted condition is also set.

public terminal class SocketReader implements Runnable {   private final SocketChannel sc;   individual final Object lock = new Object();    public SocketReader(Cord 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) {       // Forrard to handler     }   }    public static void master(String[] args)                            throws IOException, InterruptedException {     SocketReader reader = new SocketReader("somehost", 25);     Thread thread = new Thread(reader);     thread.outset();     Thread.sleep(m);     thread.interrupt();   } }          

This technique interrupts the current thread. However, it stops the thread only because the code polls the thread's interrupted condition with the Thread.interrupted() method and terminates the thread when it is interrupted. Using a SocketChannel ensures that the condition in the while loop is tested every bit soon as an interruption is received, fifty-fifty though the read is ordinarily a blocking operation. Similarly, invoking the interrupt() method of a thread blocked on a java.nio.channels.Selector also causes that thread to awaken.

Noncompliant Code Example (Database Connectedness)

This noncompliant code example shows a thread-safe DBConnector grade that creates i JDBC connection per thread. Each connection belongs to ane thread and is not shared by other threads. This is a common utilise instance considering JDBC connections are intended to be unmarried-threaded.

public final class DBConnector implements Runnable {   private final String query;    DBConnector(String query) {     this.query = query;   }    @Override public void run() {     Connection connection;     effort {       // Username and countersign are hard coded for brevity       connection = DriverManager.getConnection(           "jdbc:driver:name",            "username",            "password"       );       Argument stmt = connection.createStatement();       ResultSet rs = stmt.executeQuery(query);       // ...     } catch (SQLException e) {       // Forwards to handler     }     // ...   }    public static void principal(String[] args) throws InterruptedException {     DBConnector connector = new DBConnector("suitable query");     Thread thread = new Thread(connector);     thread.start();     Thread.sleep(5000);     thread.interrupt();   } }          

Database connections, similar sockets, lack inherent interruptibility. Consequently, this design fails to support the customer's attempts to cancel a task by endmost the resources when the corresponding thread is blocked on a long-running query, such as a bring together.

Compliant Solution (Argument.abolish())

This compliant solution uses a ThreadLocal wrapper around the connection so that a thread calling the initialValue() method obtains a unique connection instance. This approach allows provision of a cancelStatement() then that other threads or clients tin interrupt a long-running query when required. The cancelStatement() method invokes the Statement.cancel() method.

public final form DBConnector implements Runnable {   private final Cord query;   private volatile Statement stmt;    DBConnector(String query) {     this.query = query;   }    private static final ThreadLocal<Connection> connectionHolder =                                         new ThreadLocal<Connection>() {     Connection connectedness = null;      @Override public Connection initialValue() {       try {         // ...         connection = DriverManager.getConnection(             "jdbc:driver:name",              "username",              "password"         );       } catch (SQLException e) {         // Frontward to handler       }       return connexion;     }   };    public Connection getConnection() {     render connectionHolder.get();   }    public boolean cancelStatement() { // Allows client to cancel statement     Statement tmpStmt = stmt;     if (tmpStmt != null) {       endeavor {         tmpStmt.cancel();         return truthful;       } catch (SQLException e) {         // Forwards to handler       }     }     return false;   }    @Override public void run() {     try {       if (getConnection() != null) {         stmt = getConnection().createStatement();       }       if (stmt == zilch || (stmt.getConnection() != getConnection())) {         throw new IllegalStateException();       }       ResultSet rs = stmt.executeQuery(query);       // ...     } take hold of (SQLException e) {       // Frontwards to handler     }     // ...   }    public static void main(Cord[] args) throws InterruptedException {     DBConnector connector = new DBConnector("suitable query");     Thread thread = new Thread(connector);     thread.offset();     Thread.sleep(5000);     connector.cancelStatement();   } }          

The Argument.cancel() method cancels the query, provided the database management organisation (DBMS) and driver both support cancellation. It is impossible to cancel the query if either the DBMS or the driver fail to support counterfoil.

According to the Java API, Interface Statement documentation [API 2014]

By default, simply 1 ResultSet object per Argument object can be open at the same time. Equally a result, if the reading of 1 ResultSet object is interleaved with the reading of another, each must have been generated by different Argument objects.

This compliant solution ensures that only one ResultSet is associated with the Statement belonging to an instance, and, consequently, simply ane thread tin access the query results.

Adventure Cess

Failure to provide facilities for thread termination tin crusade nonresponsiveness and DoS.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

THI04-J

Low

Probable

Medium

P4

L3

Bibliography


krogerreplads1943.blogspot.com

Source: https://wiki.sei.cmu.edu/confluence/display/java/THI04-J.+Ensure+that+threads+performing+blocking+operations+can+be+terminated

0 Response to "Java Should There Be Just One Thread to Read From Socket"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel