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

WXP SP 2: Several threads cannot attempt socket connection at the same time

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not an Issue
    • Icon: P4 P4
    • None
    • 5.0
    • core-libs
    • x86
    • windows_xp

      FULL PRODUCT VERSION :
      java version "1.4.2_05"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_05-b04)
      Java HotSpot(TM) Client VM (build 1.4.2_05-b04, mixed mode)

      java version "1.4.2_06"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_06-b03)
      Java HotSpot(TM) Client VM (build 1.4.2_06-b3, mixed mode)

      java version "1.5.0"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)
      Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows XP [Version 5.1.2600] Service Pack 2

      EXTRA RELEVANT SYSTEM CONFIGURATION :
      Service Pack 2

      A DESCRIPTION OF THE PROBLEM :
      As the following program demonstrates, you can start up 10 threads, all of which are identical, except for the fact that each thread attempts a Socket connect to a different IP addresses. We intentionally chose 10 IP addresses which don't exist on our network, with the intent that all 10 connections will fail. We also set the connect "timeout" parameter to 45000 milliseconds (45 seconds), with the intent that each connect call will take a long time to failure (on Windows XP, the time to failure is a maximum of 20000 milliseconds, or 20 seconds).
       
      We also create a ServerSocket that listens on the port number specified at runtime. Assume it is port 4447.
       
      After these 10 threads have started, we sleep for 2 seconds and create an 11th thread that will attempt to connect to "localhost" on port 4447. We know that this should succeed.
       
      But instead of returning immediately, the connection request to "localhost" takes approximately 20 seconds to complete. This is because that connect request does not seem to attempt a connection until one of the initial 10 requests has timed out.
       
      The problem is further exacerbated by the fact that if you start 40 threads initially, and then start the "successful" thread, then the connect request to "localhost" will fail completely, because the "successful" thread could not run within the 20 seconds allotted by Windows (even though we request a 45 second timeout, Windows will timeout a socket connection in 20 seconds). Our guess is that the JAVA socket code is incorrectly counting down the connect timeout before the "successful thread" ever gets a chance to actually attempt to connect.
       
      Both of these problems occur in Windows XP Service Pack 2, but neither of them occurs in Windows XP Service Pack 1.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      java LocalHostTest 4447

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Expect the connection to localhost to succeed in less than a second.
      ACTUAL -
      Connection to localhost takes longer than expected or times out.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      Starting local server on port: 4447
      Wait 1 second...
      Go!
      Trying to connect to 192.168.0.10:4447, timeout = 45000ms.
      Trying to connect to 192.168.0.11:4447, timeout = 45000ms.
      Trying to connect to 192.168.0.12:4447, timeout = 45000ms.
      Trying to connect to 192.168.0.13:4447, timeout = 45000ms.
      Trying to connect to 192.168.0.14:4447, timeout = 45000ms.
      Trying to connect to 192.168.0.15:4447, timeout = 45000ms.
      Wait 2 seconds more before trying to connect to the local server...
      Trying to connect to 192.168.0.16:4447, timeout = 45000ms.
      Trying to connect to 192.168.0.17:4447, timeout = 45000ms.
      Trying to connect to 192.168.0.18:4447, timeout = 45000ms.
      Trying to connect to 192.168.0.19:4447, timeout = 45000ms.
      Go!
      Trying to connect to 127.0.0.1:4447, timeout = 45000ms.
      It took 18887ms. to connect to: 127.0.0.1
      It took 20900ms. to timed out, host: 192.168.0.11
      Connection timed out: connect (host = 192.168.0.11)
      It took 20900ms. to timed out, host: 192.168.0.12
      Connection timed out: connect (host = 192.168.0.12)
      It took 20900ms. to timed out, host: 192.168.0.13
      Connection timed out: connect (host = 192.168.0.13)
      It took 20900ms. to timed out, host: 192.168.0.14
      Connection timed out: connect (host = 192.168.0.14)
      It took 20890ms. to timed out, host: 192.168.0.15
      Connection timed out: connect (host = 192.168.0.15)
      It took 20880ms. to timed out, host: 192.168.0.16
      Connection timed out: connect (host = 192.168.0.16)
      It took 20880ms. to timed out, host: 192.168.0.17
      Connection timed out: connect (host = 192.168.0.17)
      It took 20880ms. to timed out, host: 192.168.0.18
      Connection timed out: connect (host = 192.168.0.18)
      It took 20880ms. to timed out, host: 192.168.0.19
      Connection timed out: connect (host = 192.168.0.19)
      It took 20920ms. to timed out, host: 192.168.0.10
      Connection timed out: connect (host = 192.168.0.10)

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.net.*;
      import java.io.*;
      import java.util.*;

      public class LocalHostTest
      {
          public static void runTest(int port)
          {
              // start the local server
              System.out.println("Starting local server on port: " + port);
              new Server(port).start();
              
              System.out.println("Wait 1 second...");
              try {Thread.sleep(1000); } catch (Exception xcp){}
              System.out.println("Go!");
              
              String ipAddrPrefix = "192.168.0.";
                      
              // If you change nThreads to 40 the connection to the localhost will time out
              int nThreads = 10;
              
              int base = 10;
                              
              for (int i = 0; i < nThreads; i++){
                  Client c = new Client(ipAddrPrefix + (base + i), port);
                  c.start();
              }
              
              System.out.println("Wait 2 seconds more before trying to connect to the local server...");
              try {Thread.sleep(2000); } catch (Exception xcp){}
              System.out.println("Go!");

              Client c = new Client("127.0.0.1", port);
              c.start();
          }
          
          public static void main(String args[]){
              
              if (args.length != 1){
                  System.out.println("Usage: LocalHostTest port");
                  System.exit(1);
              }
              
              int port = Integer.parseInt(args[0]);
              LocalHostTest.runTest(port);
          }
      }

      class Server extends Thread
      {
          public Server(int port)
          {
              _port = port;
          }
          
          public void run()
          {
              try {
                  ServerSocket serverSock = new ServerSocket(_port);
                  while (true){
                      try {
                          Socket s = serverSock.accept();
                          s.close();
                      }
                      catch (Exception xcp){
                          xcp.printStackTrace();
                      }
                  }
              }
              catch (Exception xcp){
                  xcp.printStackTrace();
              }
          }
          
          private int _port;
      }

      class Client extends Thread
      {
          public Client(String host, int port)
          {
              _host = host;
              _port = port;
          }

          public void run()
          {
              try {
                  connect(45000);
                  
                  // kill the program when it successfully connects to the local server
                  if (_host.startsWith("127.0.0.1")){
                      System.exit(0);
                  }
              }
              catch (Exception xcp){
                  System.out.println(xcp.getMessage() + " (host = " + _host + ")");
              }
          }

          private void connect(int timeout)
              throws IOException
          {
              System.out.println("Trying to connect to " + _host + ":" + _port + ", timeout = " + timeout +"ms.");
              Socket s = new Socket();
              InetSocketAddress inetSockAddr = new InetSocketAddress(_host, _port);
              long before = System.currentTimeMillis();
              try {
                  s.connect(inetSockAddr, timeout);
                  long took = System.currentTimeMillis() - before;
                  System.out.println("It took " + took + "ms. to connect to: " + _host);
              }
              catch (IOException ioXcp){
                  long timedOutTime = System.currentTimeMillis() - before;
                  System.out.println("It took " + timedOutTime + "ms. to timed out, host: " + _host);
                  throw ioXcp;
              }
              finally {
                  s.close();
              }
          }

          private String _host;
          private int _port;
      }
      ---------- END SOURCE ----------
      ###@###.### 2004-12-17 00:36:15 GMT

            michaelm Michael McMahon
            rmandalasunw Ranjith Mandala (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: