[kaffe] problems with thread and ServerSocket.close()

Guilhem Lavaux guilhem at kaffe.org
Fri Nov 11 13:03:21 PST 2005


Jean-frederic Clere wrote:
> Hi,
> 
> I have tried a small test program that runs correctly in Sun JVM but 
> hangs in kaffe:
> By close() on a ServerSocket I expect to cause an exception in the 
> thread where I am doing the accept() om the same ServerSocket, but the 
> close() hangs until a new connection is openned.
> 
> Any hints why the close() does not provoque an exception in the accept().
> 
> Cheers
> 
> Jean-Frederic
> 
> PS: Find attached the java code I am using.
> 
Hi Jean-Frederic,

Thanks for the bug report. I am quite slow to answer because I am 
currently very busy with my real world work. I am confirming your bug 
report. Though the behaviour of sockets is not really specified by the 
java documentation when doing simultaneous system calls (We already had 
some discussion about it for some other problem). Apparently we will 
have to support it explicitly in some cases. I will try to think about 
some safe way to do it in Classpath/kaffe.

Thanks !

Regards,

Guilhem.

> 
> ------------------------------------------------------------------------
> 
> /*
>  *  Copyright 1999-2004 The Apache Software Foundation
>  *
>  *  Licensed under the Apache License, Version 2.0 (the "License");
>  *  you may not use this file except in compliance with the License.
>  *  You may obtain a copy of the License at
>  *
>  *      http://www.apache.org/licenses/LICENSE-2.0
>  *
>  *  Unless required by applicable law or agreed to in writing, software
>  *  distributed under the License is distributed on an "AS IS" BASIS,
>  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
>  *  See the License for the specific language governing permissions and
>  *  limitations under the License.
>  */
> 
> /* @version $Id: JFCtest.java 165001 2005-04-27 16:01:42Z jfclere $ */
> 
> import java.io.*;
> import java.net.*;
> import java.text.SimpleDateFormat;
> import java.util.Date;
> import java.util.Enumeration;
> import java.util.Vector;
> 
> public class JFCtest implements Runnable {
> 
>     private ServerSocket server=null;
>     private Thread thread=null;
>     private boolean stopping=false;
>     private Vector handlers=null;
> 
>     public static native void toto();
> 
>     public JFCtest() {
>         super();
>         System.err.println("JFCtest: instance "+this.hashCode()+
>                            " created");
>         this.handlers=new Vector();
>     }
> 
>     protected void finalize() {
>         System.err.println("JFCtest: instance "+this.hashCode()+
>                            " garbage collected");
>     }
> 
>     /**
>      * init and destroy were added in jakarta-tomcat-daemon.
>      */
>     public void init()
>     throws Exception {
>         System.err.println("JFCtest: instance "+this.hashCode()+
>                            " init");
> 
>         int port=1200;
> 
>         /* Dump a message */
>         System.err.println("JFCtest: loading on port "+port);
> 
>         this.server=new ServerSocket(port);
>         this.thread=new Thread(this);
>     }
> 
>     public void start() {
>         /* Dump a message */
>         System.err.println("JFCtest: starting");
> 
>         /* Start */
>         this.thread.start();
>     }
> 
>     public void stop()
>     throws IOException, InterruptedException {
>         /* Dump a message */
>         System.err.println("JFCtest: stopping");
> 
>         /* Close the ServerSocket. This will make our thread to terminate */
>         this.stopping=true;
>         // this.server.setSoTimeout(10);
>         System.err.println("JFCtest: stopping: before close");
>         // this.thread.interrupt();
>         this.server.close();
>         System.err.println("JFCtest: stopping: after close");
> 
>         /* Wait for the main thread to exit and dump a message */
>         try {
>             this.thread.join(5000);
>         } catch (InterruptedException e) {
>         }
>         System.err.println("JFCtest: stopped");
>     }
> 
>     public void destroy() {
>         System.err.println("JFCtest: instance "+this.hashCode()+
>                            " destroy");
>     }
> 
>     public void run() {
>         int number=0;
> 
>         System.err.println("JFCtest: started acceptor loop");
>         try {
>             while(!this.stopping) {
>                 Socket socket=this.server.accept();
>                 Handler handler=new Handler(socket,this);
>                 handler.setConnectionNumber(number++);
>                 new Thread(handler).start();
>             }
>         } catch (IOException e) {
>             /* Don't dump any error message if we are stopping. A IOException
>                is generated when the ServerSocket is closed in stop() */
>             if (!this.stopping) e.printStackTrace(System.err);
>             e.printStackTrace(System.err);
>         }
> 
>         /* Terminate all handlers that at this point are still open */
>         Enumeration openhandlers=this.handlers.elements();
>         while (openhandlers.hasMoreElements()) {
>             Handler handler=(Handler)openhandlers.nextElement();
>             System.err.println("JFCtest: dropping connection "+
>                                handler.getConnectionNumber());
>             handler.close();
>         }
> 
>         System.err.println("JFCtest: exiting acceptor loop");
>     }
> 
>     protected void addHandler(Handler handler) {
>         synchronized (handler) {
>             this.handlers.add(handler);
>         }
>     }
> 
>     protected void removeHandler(Handler handler) {
>         synchronized (handler) {
>             this.handlers.remove(handler);
>         }
>     }
> 
>     public static class Handler implements Runnable {
> 
>         private JFCtest parent=null;
>         private Socket socket=null;
>         private int number=0;
> 
>         public Handler(Socket s, JFCtest p) {
>             super();
>             this.socket=s;
>             this.parent=p;
>         }
> 
>         public void run() {
>             this.parent.addHandler(this);
>             System.err.println("JFCtest: connection "+this.number+
>                                " opened from "+this.socket.getInetAddress());
>             try {
>                 InputStream in=this.socket.getInputStream();
>                 OutputStream out=this.socket.getOutputStream();
>                 handle(in,out);
>                 this.socket.close();
>             } catch (IOException e) {
>                 e.printStackTrace(System.err);
>             }
>             System.err.println("JFCtest: connection "+this.number+
>                                " closed");
>             this.parent.removeHandler(this);
>         }
> 
>         public void close() {
>             try {
>                 this.socket.close();
>             } catch (IOException e) {
>                 e.printStackTrace(System.err);
>             }
>         }
> 
>         public void setConnectionNumber(int number) {
>             this.number=number;
>         }
> 
>         public int getConnectionNumber() {
>             return(this.number);
>         }
> 
>         public void handle(InputStream in, OutputStream os) {
>             PrintStream out=null;
>             try {
>                 out=new PrintStream(os, true, "US-ASCII");
>             } catch (UnsupportedEncodingException ex) {
>                 out=new PrintStream(os);
>             }
> 
>             while(true) {
>                 try {
>                     /* If we don't have data in the System InputStream, we want
>                        to ask to the user for an option. */
>                     if (in.available()==0) {
>                         out.println();
>                         out.println("Please select one of the following:");
>                         out.println("    1) Shutdown");
>                         out.println("    2) Disconnect");
>                         out.print("Your choiche: ");
>                     }
> 
>                     /* Read an option from the client */
>                     int x=in.read();
> 
>                     switch (x) {
>                         /* If the socket was closed, we simply return */
>                         case -1:
>                             return;
> 
>                         /* Attempt to shutdown */
>                         case '1':
>                             out.println("Attempting a shutdown...");
>                             try {
>                                 this.parent.stop();
>                             } catch (Exception e) {
>                                 out.println();
>                                 out.println("Can't shutdown now");
>                                 e.printStackTrace(out);
>                             }
>                             break;
> 
>                         /* Disconnect */
>                         case '2':
>                             out.println("Disconnecting...");
>                             return;
> 
>                         /* Discard any carriage return / newline characters */
>                         case '\r':
>                         case '\n':
>                             break;
> 
>                         /* We got something that we weren't supposed to get */
>                         default:
>                             out.println("Unknown option '"+(char)x+"'");
>                             break;
> 
>                     }
> 
>                 /* If we get an IOException we return (disconnect) */
>                 } catch (IOException e) {
>                     System.err.println("JFCtest: IOException in "+
>                                        "connection "+
>                                        this.getConnectionNumber());
>                     return;
>                 }
>             }
>         }
>     }
>     public static void main(String[] args) throws Exception {
>       JFCtest mytest = new JFCtest();
>       mytest.init();   
>       mytest.start();
>     }
> }
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> kaffe mailing list
> kaffe at kaffe.org
> http://kaffe.org/cgi-bin/mailman/listinfo/kaffe





More information about the kaffe mailing list