close() of active socket does not work on FreeBSD 6

Arne H. Juul arnej at pvv.ntnu.no
Mon Dec 11 06:46:14 PST 2006


I've had problems with some tests hanging on FreeBSD 6/amd64. This happens
both with diablo-1.5.0_07-b01 and the java/jdk15 compiled from ports.

After much digging we've determined that the root cause is that
the guarantee in the socket.close() API, see the documentation at
http://java.sun.com/j2se/1.5.0/docs/api/java/net/Socket.html#close()
isn't fulfulled - the thread blocked in I/O on the socket doesn't wake up.

Here's a pretty small test program that demonstrates the problem (given
that you're running sshd on port 22, if not change the port number to
something that the program can connect to).  Is this a known problem?
Does it happen for everybody on FreeBSD 6?



import java.io.*;
import java.net.*;
import java.util.*;
import java.util.logging.*;

public class FooConn extends Thread {
     private boolean alive;
     public final int port;
     private Socket socket = null;

     public FooConn(int port) {
         super("FooConn:" + port);
         this.port = port;
         this.alive = true;
     }
     private void connect() {
         while (socket == null) {
             try {
                 socket = new Socket("localhost", port);
             } catch(IOException e) {
                 System.err.println("Connect failed: " + e);
                 try { Thread.sleep(1000); } catch(InterruptedException ie) 
{}
             }
         }
     }
     public void disconnect() throws IOException, InterruptedException {
         alive = false;
         System.out.println("closing socket");
         socket.close();
         System.out.println("calling join");
         join();
     }
     public void run() {
         while (alive) {
             if (socket == null) {
                 System.out.println("socket null, connect");
                 connect();
             }
             try {
                 int b = socket.getInputStream().read();
                 System.out.println("got byte "+ b);
             } catch (IOException e) {
                 System.out.println("IOException, set socket to null");
                 socket = null; //triggers reconnect
             } catch (RuntimeException e) {
                 System.err.println("RuntimeException "+e);
                 return;
             }
         }
     }
     public static void main(String[] args) throws IOException {
         try {
             FooConn conn = new FooConn(22);
             conn.start();
             Thread.sleep(1000);
             conn.disconnect();
         } catch(InterruptedException ie) {}
     }
}


More information about the freebsd-java mailing list