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

problem with sysCloseFD under Green threads leads to Socket errors

XMLWordPrintable

    • 1.1
    • sparc
    • solaris_9
    • Not verified

      I filed a bug report on this before, but now I can't find it, so I'm refiling. I did get
      a note from the bugtraq folks that one of my bug reports got corrupted, so perhaps
      it was this one. I'm filing this as java/runtime because there is a definite problem
      in the Green-threads code when a close happens during a read of the same
      file descriptor, but java.net.PlainSocketImpl also contributes (see my evaluation.)
      And now to the bug....

      I wrote a simple TCP proxy server using sun.net.NetworkClient and
      sun.net.NetworkServer. After I thought I had all the bugs out I still had every
      other connection get dropped immediately. Here's a modified version of the
      code that demonstrates the problem. It also includes a work-around.

      import sun.net.NetworkClient;
      import sun.net.NetworkServer;
      import java.io.IOException;
      import java.io.InputStream;
      import java.io.OutputStream;
       
      class ReaderThread extends Thread {
       
          ReaderThread(InputStream i, OutputStream o) {
              input = i;
              output = o;
          }
       
          public void run() {
              byte buf[] = new byte[2048];
              try {
                  int n;
                  while ((n = input.read(buf, 0, buf.length)) > 0) {
                      output.write(buf, 0, n);
                      output.flush();
                  }
              } catch (IOException e) {
              }
          }
          private InputStream input;
          private OutputStream output;
      }
       
      class ProxyClient extends NetworkClient {
          public ProxyClient(String host, int port) throws IOException {
              super(host, port);
          }
          public String toString() {
              return serverSocket.toString();
          }
      }
       
      class ProxyServer extends NetworkServer {
          ProxyServer(String server, int port) {
              proxyServer = server;
              proxyPort = port;
              workAround = false;
          }
          public void serviceRequest() throws IOException {
              try {
                  ProxyClient client = new ProxyClient(proxyServer, proxyPort);
                  Thread t = new ReaderThread(clientInput, client.serverOutput);
                  t.start();
                  writeSide(client);
                  // For bug to show up, ReaderThread must be in read()
                  Thread.sleep(5);
                  client.closeServer();
                  if (workAround) {
                      // Work-around bug
                      clientSocket.close();
                      t.join();
                  }
              } catch (Exception e) {
                  System.err.println("serviceRequest " + e);
              }
          }
          private void writeSide(NetworkClient client) throws IOException {
              byte buf[] = new byte[2048];
              int n;
              while ((n = client.serverInput.read(buf, 0, buf.length)) >= 0) {
                  clientOutput.write(buf, 0, n);
                  clientOutput.flush();
              }
          }
          public void tryWorkAround(boolean maybe) {
      System.out.println("tryWorkAround " + maybe);
              workAround = maybe;
          }
       
          private String proxyServer;
          private int proxyPort;
          private boolean workAround;
      }
       
      class Proxy {
          public static void main(String args[]) throws IOException {
              String httpServer = args[0];
              int httpPort = Integer.parseInt(args[1]);
              int localPort = Integer.parseInt(args[2]);
              ProxyServer p = new ProxyServer(httpServer, httpPort);
              p.startServer(localPort);
              for (int i = 0; i < 8; ++i) {
                  p.tryWorkAround((i / 4) % 2 == 1);
                  echoTest(localPort);
              }
              System.exit(0);
          }
       
          static void echoTest(int port) throws IOException {
              NetworkClient client = new NetworkClient("localhost", port);
              byte buf[] = new byte[128];
              client.serverOutput.println("GET foo");
              System.gc();
              System.runFinalization();
              System.gc();
              System.runFinalization();
              int n;
              while ((n = client.serverInput.read(buf, 0, buf.length)) > 0) {
              }
          }
      }

      % /usr/local/java/latest/bin/javac ProxyServer.java
      % /usr/local/java/latest/bin/java Proxy webcache 8080 7771
      tryWorkAround false
      tryWorkAround false
      java.io.IOException: Resource temporarily unavailable
              at java.net.SocketInputStream.read(SocketInputStream.java:89)
              at java.io.BufferedInputStream.fill(BufferedInputStream.java)
              at java.io.BufferedInputStream.read(BufferedInputStream.java)
              at Proxy.echoTest(ProxyServer.java:103)
              at Proxy.main(ProxyServer.java:89)

      % /usr/local/java/latest/bin/java_g Proxy webcache 8080 7771
      tryWorkAround false
      tryWorkAround false
      tryWorkAround false
      tryWorkAround false
      tryWorkAround true
      java.io.IOException: Bad file number
              at java.net.SocketInputStream.read(SocketInputStream.java:89)
              at java.io.BufferedInputStream.fill(BufferedInputStream.java)
              at java.io.BufferedInputStream.read(BufferedInputStream.java)
              at Proxy.echoTest(ProxyServer.java:103)
              at Proxy.main(ProxyServer.java:89)

      [ Now I change the expression for tryWorkAround from (i / 4) % 2 == 1 to
        (i / 4) % 2 == 0 so we go true, true, true, true, false, false, false, false ... ]

      springbok /tmp [130] % /usr/local/java/latest/bin/java Proxy webcache 8080 7771 tryWorkAround true
      tryWorkAround true
      tryWorkAround true
      tryWorkAround true
      tryWorkAround false
      tryWorkAround false
      tryWorkAround false
      tryWorkAround false
      serviceRequest java.io.IOException: Resource temporarily unavailable
      springbok /tmp [131] % /usr/local/java/latest/bin/java Proxy webcache 8080 7771
      tryWorkAround true
      tryWorkAround true
      tryWorkAround true
      tryWorkAround true
      tryWorkAround false
      tryWorkAround false
      tryWorkAround false
      java.io.IOException: Resource temporarily unavailable
              at java.net.SocketInputStream.read(SocketInputStream.java:89)
              at java.io.BufferedInputStream.fill(BufferedInputStream.java)
              at java.io.BufferedInputStream.read(BufferedInputStream.java)
              at Proxy.echoTest(ProxyServer.java:103)
              at Proxy.main(ProxyServer.java:89)
      ^C
      springbok /tmp [132] % /usr/local/java/latest/bin/java Proxy webcache 8080 7771
      tryWorkAround true
      tryWorkAround true
      tryWorkAround true
      tryWorkAround true
      tryWorkAround false
      tryWorkAround false
      tryWorkAround false
      tryWorkAround false
      serviceRequest java.net.SocketException: Bad file number

      springbok /tmp [133] % /usr/local/java/latest/bin/java_g Proxy webcache 8080 7771
      tryWorkAround true
      tryWorkAround true
      tryWorkAround true
      tryWorkAround true
      tryWorkAround false
      tryWorkAround false
      tryWorkAround false
      tryWorkAround false
      java.io.IOException: Bad file number
              at java.net.SocketInputStream.read(SocketInputStream.java:89)
              at java.io.BufferedInputStream.fill(BufferedInputStream.java)
              at java.io.BufferedInputStream.read(BufferedInputStream.java)
              at Proxy.echoTest(ProxyServer.java:103)
              at Proxy.main(ProxyServer.java:89)
      ^C
      springbok /tmp [134] % /usr/local/java/latest/bin/java_g Proxy webcache 8080 7771
      tryWorkAround true
      tryWorkAround true
      tryWorkAround true
      tryWorkAround true
      tryWorkAround false
      tryWorkAround false
      tryWorkAround false
      tryWorkAround false
      java.io.IOException: Resource temporarily unavailable
              at java.net.SocketInputStream.read(SocketInputStream.java:89)
              at java.io.BufferedInputStream.fill(BufferedInputStream.java)
              at java.io.BufferedInputStream.read(BufferedInputStream.java)
              at Proxy.echoTest(ProxyServer.java:103)
              at Proxy.main(ProxyServer.java:89)
      ^C

      DREL 8/23/96

            nsaraiyasunw Nakul Saraiya (Inactive)
            dlong Dean Long
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: