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

Jean-frederic Clere jfclere at sinix.net
Wed Nov 2 14:03:17 PST 2005


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.
-------------- next part --------------
/*
 *  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();
    }
}


More information about the kaffe mailing list