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

"Socket closed" reported by SocketOutputStream.write for EPIPE

    XMLWordPrintable

Details

    • hopper
    • sparc
    • solaris_8
    • Verified

    Description

      As part of SCCS delta 1.22 of src/solaris/native/java/net/SocketOutputStream.c, which was integrated for Merlin Beta 3 build 81, the following change was made:

      101c101,105
      < JNU_ThrowByName(env, "java/io/IOException", strerror(errno));
      ---
      > if (errno == EBADF || errno == EPIPE) {
      > JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
      > } else {
      > JNU_ThrowByName(env, "java/io/IOException", strerror(errno));
      > }

      The problem is that even when errno is EPIPE (not just EBADF), the detail message of the exception thrown is "Socket closed", which misleads the user into thinking that the socket was actually (locally) closed when it has not been. There is an important distinction between these two kinds of failures, and to aid in diagnosing the cause of socket/IO exceptions, this distinction should be made clear in the resulting exception text (if not the exception type), using familiar terminology.

      This bug can be demonstrated by the following example:

      import java.io.*;
      import java.net.*;

      public class BrokenWrite {

          static final int PORT = 2019;

          public static void main(String[] args) throws Exception {
              ServerSocket ss = new ServerSocket(PORT);
              Socket client = new Socket(InetAddress.getLocalHost(),
                                         ss.getLocalPort());
              Socket server = ss.accept();
              ss.close();
              new Thread(new Closer(server)).start();
              client.getOutputStream().write(new byte[1000000]);
          }

          private static class Closer implements Runnable {
              private final Socket s;
              Closer(Socket s) { this.s = s; }
              public void run() {
                  try {
                      Thread.sleep(5000);
                      s.close();
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
              }
          }
      }

      Observe the different exception detail message for this test case between Merlin Beta 3 build 81 and Merlin Beta 2:

      [terrier] 329 % java -version
      java version "1.4.0-beta3"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta3-b81)
      Java HotSpot(TM) Client VM (build 1.4.0-beta3-b81, mixed mode)
      [terrier] 330 % java BrokenWrite
      Exception in thread "main" java.net.SocketException: Socket closed
              at java.net.SocketOutputStream.socketWrite0(Native Method)
              at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:95)
              at java.net.SocketOutputStream.write(SocketOutputStream.java:117)
              at BrokenWrite.main(BrokenWrite.java:15)

      [terrier] 332 % java -version
      java version "1.4.0-beta2"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta2-b77)
      Java HotSpot(TM) Client VM (build 1.4.0-beta2-b77, mixed mode)
      [terrier] 333 % java BrokenWrite
      Exception in thread "main" java.io.IOException: Broken pipe
              at java.net.SocketOutputStream.socketWrite0(Native Method)
              at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:95)
              at java.net.SocketOutputStream.write(SocketOutputStream.java:117)
              at BrokenWrite.main(BrokenWrite.java:15)

      Attachments

        Activity

          People

            alanb Alan Bateman
            peterjones Peter Jones
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: