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

can't unblock read() of InputStream from URL connection

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • 1.4.0
    • 1.3.0
    • core-libs
    • None
    • beta
    • unknown
    • generic

      one thread reads on an input stream which it gets from
      an http url connection. if the read() blocks (eg. because
      of network problems) and another thread tries to close()
      the input stream then the close() also blocks.

      the close() is waiting on a monitor.

      there is no clean way of unblocking the threads.

      customer is seeing this problem with an applet (both using
      and not using a proxy server for the http url connection)
      but it is also reproducible as an application.

      here's a testcase:

      there are 2 programs urlserver & urlclose.

      urlserver listens on port 12345. when it receives a connection
      it serves up the http header (which says there are 2000 bytes
      of data following) & and the first few bytes of data. it then
      sleeps for 60 seconds before exiting.

      urlclose connects to the url http://localhost:12345/ and
      reads from the InputStream it gets from the URL. another
      thread sleeps for 5 seconds & then closes the InputStream.
      this close() blocks waiting on a monitor.


      in 1.2 the read does at least unblock when the peer closes
      the socket (at which point the close can complete). however,
      in 1.3 even this does not unblock the threads.

      ==> urlclose.java <==
      import java.io.*;
      import java.net.*;

      public class urlclose implements Runnable{

              public static void main(String[] args){
                      String urlStr = "http://localhost:12345/";
                      if(args.length > 0)
                              urlStr = args[0];

                      try{
                              System.out.println("attempting connection to " + urlStr);
                              URL url = new URL(urlStr);
                              URLConnection conn = url.openConnection();
                              conn.connect();
                              System.out.println("connected");
                              InputStream is = conn.getInputStream();
                              System.out.println("InputStream = " + is);

                              System.out.println("starting thread");
                              Runnable runMe = new urlclose(is);
                              Thread t = new Thread(runMe);
                              t.start();

                              int num_read = 0;
                              byte[] buf = new byte[1024];
                              while((num_read = is.read(buf, 0, buf.length)) > 0){
                                      String str;
                                      if(num_read > 60)
                                              str = new String(buf,0,60,"US-ASCII") + "....";
                                      else
                                              str = new String(buf,0,num_read,"US-ASCII");
                                      System.out.println("read " + num_read + " byte" +
                                                      (num_read==1?"":"s") + ": " + str);
                              }

                              System.out.println("finished reading");
                              t.join();
                      }
                      catch(Exception e){
                              System.out.println("reading thread: caught exception " + e);
                              e.printStackTrace();
                      }
              }

              InputStream is;

              public urlclose(InputStream is){
                      this.is = is;
              }

              public void run(){
                      try{
                              Thread.sleep(5000);
                              System.out.println("gonna close " + is);
                              is.close();
                              System.out.println("closed " + is);
                      }
                      catch(Exception e){
                              System.out.println("caught exception " + e);
                              e.printStackTrace();
                      }
              }

      }

      ==> urlserver.java <==
      import java.io.*;
      import java.net.*;

      public class urlserver{

              public static void main(String[] args){
                      int port = 12345;
                      if(args.length > 0){
                              try{
                                      port = new Integer(args[0]).intValue();
                              }catch(NumberFormatException nfe){
                                      System.out.println("invalid port " + args[0] +
                                              " - using " + port + " instead");
                              }
                      }
                      try{
                              ServerSocket ss = new ServerSocket(port);
                              System.out.println("waiting for connection");
                              Socket s = ss.accept();
                              System.out.println("got connection");
                              OutputStream os = s.getOutputStream();
                              String resp = "HTTP/1.1 200 OK\r\nContent-Length: " +
                                      "2000\r\nContent-Type: text/html\r\n\r\n";
                              resp += "<html><head>test</head>\n<body>hello...";
                              byte[] b = resp.getBytes("US-ASCII");
                              os.write(b,0,b.length);
                              Thread.sleep(60000);
                      }catch(Exception e){
                      }
              }
      }

            michaelm Michael McMahon
            duke J. Duke
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: