Server is not closing gracefully

Try closing the connections first so that you can kick them gracefully and see if the issue still happens.

for(HostedConnection hostedConnection : server.getConnections()){
    hostedConnection.close(null);
}
server.close();

I tried this, but the two threads are still running.

EDIT: I even tried closing the connections, then waiting for the connectionRemoved listener and after the last one is removed, closing the server. Still, those two threads are running. :frowning:
EDIT 2: Also tried disconnecting the clients first by sending them a message, and then after all clients disconnected, closing the server… But the Kernel Threads are still alive.

Well, it’s strange because I only have this issue when there is a connection jammed. The threads are supposed to shut down.

It seems unlikely but it could be that your own game code is complicit in the issue. You could try making a simple test case and seeing if it also happens.

I have no idea if one can make things that easy, but try this:

package testserver;

import java.util.Set;
import com.jme3.network.Network;
import com.jme3.network.Server;

public class TestServer{

    public static void main(String[] args){
        try{
            Server server = Network.createServer(33900);
            System.out.println("Starting server...");
            server.start();
            Thread.sleep(3000);
            printThreads();
            Thread.sleep(3000);
            System.out.println();
            System.out.println("Closing server...");
            server.close();
            Thread.sleep(3000);
            printThreads();
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }
    
    private static void printThreads(){
        Set<Thread> threads = Thread.getAllStackTraces().keySet();
        System.out.println(threads.size() + " threads:");
        for(Thread thread : threads){
            System.out.println(thread);
        }
    }
}

Starting server…
9 threads:
Thread[Signal Dispatcher,9,system]
Thread[Selector@0.0.0.0/0.0.0.0:33900,5,main]
Thread[UDP Host@0.0.0.0/0.0.0.0:33900,5,main]
Thread[com.jme3.network.kernel.udp.UdpKernel@8c678c7,5,main]
Thread[Finalizer,8,system]
Thread[com.jme3.network.kernel.tcp.SelectorKernel@2b2143d8,5,main]
Thread[Reference Handler,10,system]
Thread[main,5,main]
Thread[Attach Listener,5,system]

Closing server…
7 threads:
Thread[Signal Dispatcher,9,system]
Thread[com.jme3.network.kernel.udp.UdpKernel@8c678c7,5,main]
Thread[Finalizer,8,system]
Thread[com.jme3.network.kernel.tcp.SelectorKernel@2b2143d8,5,main]
Thread[Reference Handler,10,system]
Thread[main,5,main]
Thread[Attach Listener,5,system]
BUILD SUCCESSFUL (total time: 9 seconds)

My game is indeed a lot more complex and I don’t know if the above counts as a real test case since it’s all in one thread and method, but at least the two threads are still there at the end.

EDIT: I created this inside a normal Java application (no jME basic game project) with just the jme-network library added.

But the application closes, yes? So eventually those threads shut down.

Edit: in fact you aren’t printing if they are still active or not.

Well, in that specific test case, yes.
But in my game the application doesn’t shut down and I want to start new servers without having a memory leak or similar stuff.

Oh, that might be true - I will try to find a way to check that. Maybe they are in fact inactive. Still strange that they are kept in there.

Ah, yeah… they are daemon threads so they don’t keep the app open. (Probably a mistake actually.)

The only thing I can think is that on your platform, closing the selector doesn’t throw an exception from select().

I added an isAlive() to the output, maybe this is what describes if the thread is active?

9 threads:
true Thread[Finalizer,8,system]
true Thread[Signal Dispatcher,9,system]
true Thread[Reference Handler,10,system]
true Thread[Selector@0.0.0.0/0.0.0.0:33900,5,main]
true Thread[UDP Host@0.0.0.0/0.0.0.0:33900,5,main]
true Thread[com.jme3.network.kernel.udp.UdpKernel@40f92a41,5,main]
true Thread[Attach Listener,5,system]
true Thread[main,5,main]
true Thread[com.jme3.network.kernel.tcp.SelectorKernel@787db430,5,main]

Closing server…
7 threads:
true Thread[Signal Dispatcher,9,system]
true Thread[Finalizer,8,system]
true Thread[Reference Handler,10,system]
true Thread[com.jme3.network.kernel.udp.UdpKernel@40f92a41,5,main]
true Thread[Attach Listener,5,system]
true Thread[main,5,main]
true Thread[com.jme3.network.kernel.tcp.SelectorKernel@787db430,5,main]

I even thought about shutting them down manually, but all I got was an UnexpectedInterruptionException I think^^

It seems these are not the threads I thought they were.

I’ve found the issue… and hopefully a fix. I’m about to test it. I’ll post back when I have but thanks for pushing on this.

1 Like

Nice. :slight_smile: Well, I have to thank you for the fast response. No need to hurry.

BTW, you should really consider upgrading… at least the networking. A whole new service model was added. Very useful.

A slightly enhanced version of your app that let me track down the issue:

package tester;

import java.util.Set;
import com.jme3.network.Network;
import com.jme3.network.Server;


public class Test {

    public static void main(String[] args){
        try{
            Server server = Network.createServer(33900);
            System.out.println("Starting server...");
            server.start();
            Thread.sleep(3000);
            printThreads(false);
            Thread.sleep(3000);
            System.out.println();
            System.out.println("Closing server...");
            server.close();
            System.out.println("Server closed.");
            Thread.sleep(3000);
            printThreads(true);
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }

    private static void printThreads( boolean showStack ){
        Set<Thread> threads = Thread.getAllStackTraces().keySet();
        System.out.println(threads.size() + " threads:");
        for(Thread thread : threads){
            System.out.println(thread);
            if( showStack ) {
                printStack(thread);
            }
        }
    }
    
    private static void printStack( Thread thread ) {
        for( StackTraceElement el : thread.getStackTrace() ) {
            System.out.println("   " + el);
        }
    }
}


Output after my changes:

run-single:
Starting server...
9 threads:
Thread[Reference Handler,10,system]
Thread[UDP Host@0.0.0.0/0.0.0.0:33900,5,main]
Thread[com.jme3.network.kernel.udp.UdpKernel@1f02b85,5,main]
Thread[Signal Dispatcher,9,system]
Thread[Selector@0.0.0.0/0.0.0.0:33900,5,main]
Thread[main,5,main]
Thread[Finalizer,8,system]
Thread[com.jme3.network.kernel.tcp.SelectorKernel@182ef6b,5,main]
Thread[Attach Listener,5,system]

Closing server...
Server closed.
5 threads:
Thread[main,5,main]
   java.lang.Thread.getStackTrace(Thread.java:1567)
   muddy.Test.printStack(Test.java:82)
   muddy.Test.printThreads(Test.java:76)
   muddy.Test.main(Test.java:64)
Thread[Reference Handler,10,system]
   java.lang.Object.wait(Native Method)
   java.lang.Object.wait(Object.java:503)
   java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
Thread[Finalizer,8,system]
   java.lang.Object.wait(Native Method)
   java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
   java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
   java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:177)
Thread[Signal Dispatcher,9,system]
Thread[Attach Listener,5,system]
BUILD SUCCESSFUL (total time: 28 seconds)

First once I found the threads that were still running, I added a join() to the code that was supposed to close them… then the app hung indefinitely. After that it was easier to see the fix when I did it.

Changes are checked into 3.1 master.

1 Like

Great to hear! I guess, I will look into updating to 3.1 then. :smiley: