Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6734169

Async close of Socket causes NullPointerException from getOutputStream

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Won't Fix
    • Icon: P4 P4
    • None
    • 6
    • core-libs
    • x86
    • linux

      FULL PRODUCT VERSION :
      java version "1.6.0_07"
      Java(TM) SE Runtime Environment (build 1.6.0_07-b06)
      Java HotSpot(TM) 64-Bit Server VM (build 10.0-b23, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      Linux bagel 2.6.16.46-0.12-smp #1 SMP Thu May 17 14:00:09 UTC 2007 x86_64 x86_64 x86_64 GNU/Linux

      A DESCRIPTION OF THE PROBLEM :
      Asynchronously closing a socket while another thread is calling getOutputStream can cause the thread calling getOuputStream to receive a NullPointerException instead of the expected IOException.

      ava.lang.NullPointerException
      at java.io.FileOutputStream.<init>(FileOutputStream.java:201)
      at java.net.SocketOutputStream.<init>(SocketOutputStream.java:41)
      at java.net.PlainSocketImpl.getOutputStream(PlainSocketImpl.java:420)
      at java.net.Socket$3.run(Socket.java:819)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.net.Socket.getOutputStream(Socket.java:816)
      at quicktests.SocketClose.main(SocketClose.java:59)

      Looking at the source, it appears that java.net.PlainSocketImpl is not protected from an asynchronous close. There is nothing to prevent fd field from being set to null between The call to isClosedOrPending() and the call to new SocketOutputStream(this) because close never synchronizes on PlainSocketImpl;


          /**
           * Gets an OutputStream for this socket.
           */
          protected synchronized OutputStream getOutputStream() throws IOException {
      if (isClosedOrPending()) {
      throw new IOException("Socket Closed");
      }
              if (shut_wr) {
      throw new IOException("Socket output is shutdown");
      }
      return new SocketOutputStream(this);
          }

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      So far, I have only been able to reproduce this failure with a debugger. If you use the following test and set a breakpoint on the line

      return new SocketOutputStream(this); in PlainSocketImpl.getOutputStream, The test will get a null pointer exception once you continue on from the breakpoint because the close thread asynchronously closed the socket.


      REPRODUCIBILITY :
      This bug can be reproduced rarely.

      ---------- BEGIN SOURCE ----------
      package quicktests;

      import java.io.IOException;
      import java.io.OutputStream;
      import java.net.ServerSocket;
      import java.net.Socket;
      import java.net.UnknownHostException;

      /**
       * A test which demonstrates that a socket can throw
       * a NullPointerException from socket.getInputStream if
       * it is asynchronously closed.
       * @author dsmith
       *
       */
      public class SocketClose {

        private static final int SERVER_PORT = 44332;

        public static void main(String[] args) throws UnknownHostException, IOException {
          
          //create a server socket to listen for connections.
          final ServerSocket serverSocket = new ServerSocket(SERVER_PORT);
          Thread serverThread = new Thread("Server thread") {
            public void run() {
              while(true) {
                try {
                  Socket socket = serverSocket.accept();
      // System.out.println("We have a client.");
                  socket.getInputStream().read();
      // System.out.println("Client went away");
                } catch(Exception e) {
                  e.printStackTrace();
                  break;
                }
              }
            }
          };
          serverThread.start();
          
          
          try {
              final Socket socket = new Socket("localhost", SERVER_PORT);
              
              Thread closeThread = new Thread("client thread") {
                public void run() {
                  try {
                    socket.close();
                  } catch (Exception e) {
                    e.printStackTrace();
                  }
                }
              };
              closeThread.start();


              try {
                OutputStream os = socket.getOutputStream();
              } catch(IOException ok) {
                System.out.println("Socket was closed ok " + ok);
              } catch(NullPointerException bad) {
                System.err.println("Got a null pointer exception");
                bad.printStackTrace();
                throw bad;
              }
            
          } finally {
            serverSocket.close();
          }
          
        }
      }

      ---------- END SOURCE ----------

            vtewari Vyom Tewari
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: