Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4504764
Votes 0
Synopsis Socket.read() doesn't return when Socket.close() is called under Linux
Category java:classes_net
Reported Against merlin-beta2
Release Fixed
State 11-Closed, duplicate of 4344135, bug
Priority: 2-High
Related Bugs 4344135
Submit Date 19-SEP-2001
Description




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

This bug is only under Linux and only when the client and the server are on the
same computer (localhost).
I create a server socket and a client socket, the server socket only accept one
client and wait for a byte (socket.getInputStream().read()).
The client connect to the server, launch an other thread used to close the
socket after 3 seconds.After launching this thread, but before the
socket.close(), the client wait for a byte on the input stream of the socket.
Under Windows, when the client close his socket, the call to read on the server
side unblock, returing -1 and I can handle client disconnection.
But under Linux, even if the socket.close() success (log before and after the
call to socket.close()),the read on the client does not return and is still
blocked, I think because the socket is not really closed by the OS.
As a result, the server call to read does not return either, and the client
disconnection is not detected.

Here is the code sample of this bug ( 2 files ServerSocketTest.java and
ClientSocketTest.java)

/*************************ServerSocketTest.java*******************************/
import java.io.*;
import java.net.*;

public class  ServerSocketTest {

  private static final int DEFAULT_PORT = 3000;

/**
 * Wait for a client connection, and then wait for a byte
 * from this client.
 */
  public ServerSocketTest() {
    try{
      ServerSocket srvSock = new ServerSocket(DEFAULT_PORT);
      Socket s = srvSock.accept();
      System.out.println("Client connected from " + s.getInetAddress());
      System.out.println("Start reading 1 byte");
      int read = s.getInputStream().read();
      if (read == -1) throw new IOException("EOF reached");
      System.out.println("Byte read ok");
    } catch (IOException ioe) {
      System.out.println("Client disconnected");
      ioe.printStackTrace();
    }
  }

  public static void main(String[] args) {
    new ServerSocketTest();
  }

}

/*************************ClientSocketTest.java*******************************/
import java.io.*;
import java.net.*;

public class  ClientSocketTest {

  private static final int DEFAULT_PORT = 3000;

  /**
   * Class use to close the socket.
   * Wait 3 seconds in an other thread and close the Socket.
   */
  class SocketCloser implements Runnable {
    Socket s;
    public SocketCloser(Socket s){
      this.s = s;
    }

    public void run() {
      synchronized (this) {
        try{ this.wait(3000); } catch (InterruptedException ie) {
ie.printStackTrace(); }
      }
      System.out.println("Closing socket");
      try{ s.close(); } catch (IOException ioe) { ioe.printStackTrace(); }
      System.out.println("Socket closed");
    }
  }

  /**
   * Create the socket, start the SocketCloser thread and
   * wait for a byte on the input stream of the socket.
   */
  public ClientSocketTest(){
    try{
      Socket socket = new Socket("127.0.0.1",DEFAULT_PORT);
      (new Thread(new SocketCloser(socket))).start();
      System.out.println("Start reading 1 byte");
      int read = socket.getInputStream().read();
      if (read == -1) throw new IOException("EOF reached");
      System.out.println("Read byte ok");
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }
  }

  public static void main(String[] args) {
    new ClientSocketTest();
  }
}

No trace and no Exception.
(Review ID: 132110) 
======================================================================
Work Around
N/A
Evaluation
The workaround in 1.3.1 is to define J2SE_PREEMPTIVECLOSE environment
variable - see release notes for details.

In merlin this has been fixed in beta3 so closing as a dup of 4344135.

  xxxxx@xxxxx   2001-09-20
Comments
  
  Include a link with my name & email   

Submitted On 08-MAR-2002
niall.smart
The comment above is wrong - the environment variable is
named J2SE_PREEMPTCLOSE - I don't need more confusion!!


Submitted On 26-JUN-2002
hansenb
Set the socket's soTimeout, if no data is read within that 
time the read function will abort and if the socket is 
closed any future I/O calls will fail.



PLEASE NOTE: JDK6 is formerly known as Project Mustang