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

read() on a socket fails

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P1
    • Resolution: Not an Issue
    • Affects Version/s: 2.0.1_build12, 2.0_beta24, 1.1, 1.1.4, 1.2.1
    • Fix Version/s: None
    • Component/s: core-libs
    • Labels:
    • Subcomponent:
    • CPU:
      generic, x86, sparc
    • OS:
      solaris_2.5.1, solaris_2.6, solaris_7, windows_95

      Description

      [chamness 1/12/97] Update.
      When running multiple threads, a thread that is invoking read()
      on a socket can go to sleep. The other side of the socket
      continues to write to this sleeping thread. The reading thread
      eventually hangs. It can hang on a single byte read. So while reading
      an integer, it can get a corrupt value.

      Setting the timeout period with Socket.setSoTimeout() will
      cause the reading thread to throw an InterruptedIOException,
      and get out of the hung state. But this is not a true
      timeout.

      If output streams are not buffered, windows 95 can crash.

      ======================================================================
      Name: mc57594 Date: 02/14/97

      First some background as to how we found this problem. We are
      developing a client in Java which talks to a server. One of our
      developers works from home and thus dials in over a slow line (28.8).
      The java client sends a request to the server and then waits for a
      reply. The connection is over a TCP socket. It is setup as:
      try {
      socket = new Socket(client.ip, client.port);
      }
      catch (UnknownHostException ex) {}
      catch (IOException ex) { PtkUtil.PtkcExit(client, "Can't create socket.", 1); }
      try {
                  din = new DataInputStream(socket.getInputStream());
                  dout = new DataOutputStream(socket.getOutputStream());
      }
      catch (IOException ex) { PtkUtil.PtkcExit(client, "Can't create input/output stream.", 1); }
          We used to receive our replies back using code like:
      try {
      size = _din.readShort();
      version = _din.readInt();
      ...
      } catch (IOException e) {
      System.out.println("Reading header exception "+e);
      return false;
      }
      return true;
          Now normally this works just fine. We normally test the client and
      server over an ethernet LAN and no problems. Today we had a developer
      working from home and then tried the client/server connection over the
      internet and 28.8K modem. We then encountered problems. The server
      is attempting to send a client a 1460 byte response which is having
      to be retransmitted multiple times (as seen with a #snoop).
          Under JDK1.0.2, the client goes into the first
      size = _din.readShort();
      and never returns.
          Under JDK1.1Beta3.3, the client goes into the first
      size = _din.readShort();
      and eventually goes to the catch block with
      Reading header exception java.io.IOException: Resource temporarily unavailable
          Our suspicion with JDK1.0.2 is that the read thread is going infinite
      looping considering the response from JDK1.1Beta3.3. IE, it is catching
      the exception and trying to deal with it but failing. In either case,
      there really is data "in the pipe" so readShort() should not have failed;
      the socket was not closed or broken.

          I extracted the src.zip and looked in java/io/DataInputStream.java
      at the readShort() function. It looks like:
      public final short readShort() throws IOException {
      InputStream in = this.in;
      int ch1 = in.read();
      int ch2 = in.read();
      if ((ch1 | ch2) < 0)
      throw new EOFException();
      return (short)((ch1 << 8) + (ch2 << 0));
      }
      Unfortunately under JDK1.1Beta3 we get the IOException, but we don't know
      which byte (ch1 or ch2) caused the exception. Thus we cannot easily
      try again.
          Under JDK1.1Beta3.3, you have socket.getTcpNoDelay() and
      socket.getSoTimeout(). They are 'false' and '0' respectively.

      ----------
          Instead of reading our data structure in a field at a time, I
      decided to read in the entire header and then parse it apart. Normally
      I would use readFully() for this. But we have the same problem with
      readFully() and readShort(); IE, if we get an IOException we don't know
      how much data has been read in so far. Thus we decided to come up with
      our own readFully() function:
          public static int readFully(DataInputStream in, byte [] b, int off, int len)
                      throws EOFException
          {
              int count;
              int n = 0;
              while (n < len) {
                  try {
                      System.out.println("readFully of "+(len-n)+" bytes at offset "+(
      off+n));
                      count = in.read(b, off + n, len - n);
                      System.out.println("readFully count="+count);
                  }
                  catch (IOException e) {
                      /* Try again */
                      System.out.println("readFully: exception " + e);
                      continue;
                  }
                  if (count <= 0)
                      throw new EOFException();
                  n += count;
              }
              return n;
          }
      The idea here (based upon our developers experience) is that when an
      IOException occurs to just ignore it and try again. In the one case
      (slow link) we know there really is more data available. But, now
      I cannot detect the differenence between EOF and a bad exception.
      IE, if we enter this readFully() and actually close the socket, then
      we get the same IOException:
      readFully: exception java.io.IOException: Resource temporarily unavailable
      as when the bytes were really temporarily unavailable. Now what?


      In general it appears there is some edge condition where the various
      blocking read*() calls are failing. In JDK1.0.2 they go infinite loop
      (best guess since we never come out of the call) and in JDK1.1Beta3.3,
      we get an "java.io.IOException: Resource temporarily unavailable" when
      we should not. What is the fix?
      ======================================================================

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              jccollet Jean-Christophe Collet (Inactive)
              Reporter:
              mchamnessunw Mark Chamness (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: