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

(spec) InputStream.read() implementations block when they should return immediately

XMLWordPrintable

    • b81
    • generic
    • generic

      Name: bsC130419 Date: 07/13/2001


      happens in many JREs, including Apple's MRJ 2.2/Mac, and Sun's JRE 1.3/Linux

      /* BufferedInputStream blocking problem

      Problem:

         BufferedInputStream blocks until enough bytes are available to fill its
         internal buffer, even if fewer bytes have been requested. In a client/
         server application, this can cause a deadlock: the client waits forever
         for the buffer to be filled, while the server waits forever for the
         client to finish processing the response and issue another request.

      The output of this test program should look like this:

          $ java BisBugTest
          read 0x1020304 in 0 milliseconds.
          read 0x1020304 in 1004 milliseconds.
          read 0x1020304 in 1010 milliseconds.
          read 0x1020304 in 1010 milliseconds.
          read 0x1020304 in 1010 milliseconds.

      Instead, it looks like this:

          $ java BisBugTest
          read 0x1020304 in 515964 milliseconds.
          read 0x1020304 in 0 milliseconds.
          read 0x1020304 in 0 milliseconds.
          read 0x1020304 in 0 milliseconds.
          read 0x1020304 in 0 milliseconds.

      In this test run, the first read was delayed by 516 seconds (about 9 minutes).
      */

      import java.io.*;

      public class BisBugTest {

         public static void main (String args []) {
            try {
                // This creates a stream that sends 1,2,3,4; waits 1 second; repeats
                InputStream r = new RepeatStream (new byte [] {1, 2, 3, 4}, 1000);
                DataInputStream d = new DataInputStream (new BufferedInputStream
      (r));
             // DataInputStream d = new DataInputStream (r); // this way it works OK
                while (true) {
                   long start = System.currentTimeMillis ();
                   int i = d.readInt ();
                   long end = System.currentTimeMillis ();
                   System.out.print ("read 0x" + Integer.toHexString (i));
                   System.out.println (" in " + (end - start) + " milliseconds.");
                }
            } catch (Exception e) {
                e.printStackTrace ();
            }
         }

         // This input stream emulates a server that sends a series of bytes, waits a
         // while, sends the same series of bytes again, waits again, ad infinitum...
         public static class RepeatStream extends InputStream {

            private int sleepMillis;
            private byte contents [];
            private int index = 0;

            public RepeatStream (byte contents [], int sleepMillis) {
               this.contents = contents;
               this.sleepMillis = sleepMillis;
            }

            public int available () {
               return contents.length - index;
            }

            public int read ()
            throws IOException {
               if (index == contents.length) {
                  sleep (sleepMillis);
                  index = 0;
               }
               return contents [index++] & 0xff;
            }

            private static void sleep (int timeout)
            throws IOException {
               try {
                  Thread.sleep (timeout);
               } catch (InterruptedException e) {
                  throw new InterruptedIOException (e.getMessage ());
               }
            }
         }
      }


      (Review ID: 126530)
      ======================================================================

            chegar Chris Hegarty
            bstrathesunw Bill Strathearn (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: