onException/onDisconnect/onClose are not delivered to DefaultSessionEventHandler
nikolaykuz opened this issue · comments
I have following scenario. There are 3 players in the game room, so there are 3 SessionHandlers. I shutdown one of the players. So it is SessionHandler detects that and prints onException. Then I have a code inside ServerGameManager that sends a NETWORK_MESSAGE to other clients of the same game to shutdown also.
But for two other clients handlers of their SessionHandlers are never called.
public class SessionHandler extends DefaultSessionEventHandler {
//example
@Override
protected void onException(Event event) {
System.out.println("onException");
}
@Override
protected void onDisconnect(Event event) {
System.out.println("onDisconnect");
}
@Override
protected void onClose(Event event) {
System.out.println("onClose");
}
2013-04-23 15:22:07,841 [DefaultToServerHandler.java:49][ERROR]:Exception in DefaultToServerHandler class: [id: 0x03ecf7ad, /10.254.215.116:60277 => /10.254.215.116:81] EXCEPTION: java.io.IOException: An existing connection was forcibly closed by the remote host.
2013-04-23 15:22:07,842 [DefaultToServerHandler.java:60][DEBUG]:Channel 65861549 is disconnected, raising the event to session
2013-04-23 15:22:07,842 [SessionHandler.java:60][ERROR]:GAMEROOM1 PLAYER[0] onException
2013-04-23 15:22:07,842 [DefaultToServerHandler.java:78][DEBUG]:Channel 65861549 is closed and resources released
2013-04-23 15:22:07,842 [NettyTCPMessageSender.java:57][INFO]:Going to close tcp connection in class: org.menacheri.jetserver.communication.NettyTCPMessageSender
2013-04-23 15:22:07,842 [NettyTCPMessageSender.java:66][WARN]:Unable to write the Event Event [type=34, source=null, timeStamp=1366698127842] with type 34 to socket
2013-04-23 15:22:07,843 [JetlangEventDispatcher.java:260][TRACE]:Entered removeHandlersForSession for session PlayerSession [id=1player=org.menacheri.jetserver.app.impl.DefaultPlayer@d5904c89, parentGameRoom=org.evogame.server.RealGameRoom@50, protocol=null, isShuttingDown=true]
2013-04-23 15:22:07,843 [JetlangEventDispatcher.java:272][TRACE]:Going to remove 1 handlers for session: PlayerSession [id=1player=org.menacheri.jetserver.app.impl.DefaultPlayer@d5904c89, parentGameRoom=org.evogame.server.RealGameRoom@50, protocol=null, isShuttingDown=true]
2013-04-23 15:22:07,843 [JetlangEventDispatcher.java:284][TRACE]:Going to clear handlers on dispatcher org.menacheri.jetserver.event.impl.JetlangEventDispatcher@925c95
2013-04-23 15:22:07,843 [ServerGameManager.java:145][INFO]:GAMEROOM1 PLAYER[0] has disconnected!
2013-04-23 15:22:07,854 [DefaultToServerHandler.java:60][DEBUG]:Channel 476923117 is disconnected, raising the event to session
2013-04-23 15:22:07,854 [DefaultToServerHandler.java:78][DEBUG]:Channel 476923117 is closed and resources released
2013-04-23 15:22:07,854 [DefaultSessionEventHandler.java:179][DEBUG]:Received disconnect event in session. Going to close session
2013-04-23 15:22:07,854 [NettyTCPMessageSender.java:57][INFO]:Going to close tcp connection in class: org.menacheri.jetserver.communication.NettyTCPMessageSender
2013-04-23 15:22:07,854 [NettyTCPMessageSender.java:66][WARN]:Unable to write the Event Event [type=34, source=null, timeStamp=1366698127854] with type 34 to socket
2013-04-23 15:22:07,855 [JetlangEventDispatcher.java:260][TRACE]:Entered removeHandlersForSession for session PlayerSession [id=2player=org.menacheri.jetserver.app.impl.DefaultPlayer@3c452253, parentGameRoom=org.evogame.server.RealGameRoom@50, protocol=null, isShuttingDown=true]
2013-04-23 15:22:07,855 [JetlangEventDispatcher.java:272][TRACE]:Going to remove 1 handlers for session: PlayerSession [id=2player=org.menacheri.jetserver.app.impl.DefaultPlayer@3c452253, parentGameRoom=org.evogame.server.RealGameRoom@50, protocol=null, isShuttingDown=true]
2013-04-23 15:22:07,855 [JetlangEventDispatcher.java:284][TRACE]:Going to clear handlers on dispatcher org.menacheri.jetserver.event.impl.JetlangEventDispatcher@18309b0
2013-04-23 15:22:07,855 [DefaultSessionEventHandler.java:179][DEBUG]:Received disconnect event in session. Going to close session
2013-04-23 15:22:07,856 [DefaultToServerHandler.java:60][DEBUG]:Channel -395629090 is disconnected, raising the event to session
2013-04-23 15:22:07,856 [DefaultToServerHandler.java:78][DEBUG]:Channel -395629090 is closed and resources released
2013-04-23 15:22:07,856 [DefaultSessionEventHandler.java:179][DEBUG]:Received disconnect event in session. Going to close session
2013-04-23 15:22:07,856 [NettyTCPMessageSender.java:57][INFO]:Going to close tcp connection in class: org.menacheri.jetserver.communication.NettyTCPMessageSender
2013-04-23 15:22:07,856 [NettyTCPMessageSender.java:66][WARN]:Unable to write the Event Event [type=34, source=null, timeStamp=1366698127856] with type 34 to socket
2013-04-23 15:22:07,856 [JetlangEventDispatcher.java:260][TRACE]:Entered removeHandlersForSession for session PlayerSession [id=3player=org.menacheri.jetserver.app.impl.DefaultPlayer@4536c9ea, parentGameRoom=org.evogame.server.RealGameRoom@50, protocol=null, isShuttingDown=true]
2013-04-23 15:22:07,857 [JetlangEventDispatcher.java:272][TRACE]:Going to remove 1 handlers for session: PlayerSession [id=3player=org.menacheri.jetserver.app.impl.DefaultPlayer@4536c9ea, parentGameRoom=org.evogame.server.RealGameRoom@50, protocol=null, isShuttingDown=true]
2013-04-23 15:22:07,857 [JetlangEventDispatcher.java:284][TRACE]:Going to clear handlers on dispatcher org.menacheri.jetserver.event.impl.JetlangEventDispatcher@c6824e
2013-04-23 15:22:07,857 [DefaultSessionEventHandler.java:179][DEBUG]:Received disconnect event in session. Going to close session
Could you provide the code you have in ServerGameManager that will disconnect the other 2 sessions. I will look into this in parallel.
Channel.close();
System.exit(0);
combinations of both
any reason why you dont use playerSession.close()
instead?
at client side I don't have playerSession. I mean ServerGameManager sends some message to clients, upon reception they invoke
Channel.close();
System.exit(0);
@nikolaykuz I haven't had time to look at this, will do so later today/tomorrow and let you know.
Hopefully, in this week :)
@nikolaykuz I wrote a unit test and it seems to work as expected. The subclass is getting the events. Even in your logs, I can see that the disconnect session event is reach the super class DefaultSessionEventDispatcher
.
@Test
public void multiSessionDisconnectValidation() throws InterruptedException {
// create necessary setup objects.
Game game = new SimpleGame(1, "Test");
Protocol dummyProtocol = new DummyProtocol();
GameRoomSessionBuilder sessionBuilder = new GameRoomSessionBuilder();
sessionBuilder.parentGame(game).gameRoomName("Zombie_ROOM_1")
.protocol(dummyProtocol);
CountDownLatch latch1 = new CountDownLatch(2);
CountDownLatch latch2 = new CountDownLatch(2);
AtomicLong counter = new AtomicLong(0l);
Session gameRoomSession = new TestGameRoom(sessionBuilder, counter,
latch1);
GameRoom gameRoom = (GameRoom) gameRoomSession;
PlayerSession playerSession = gameRoom.createPlayerSession(null);
PlayerSession playerSession2 = gameRoom.createPlayerSession(null);
PlayerSession playerSession3 = gameRoom.createPlayerSession(null);
gameRoom.connectSession(playerSession);
gameRoom.connectSession(playerSession2);
gameRoom.connectSession(playerSession3);
playerSession.addHandler(new SessionHandlerLatchCounter(playerSession,
counter, latch1));
playerSession2.addHandler(new SessionHandlerLatchCounter(playerSession2,
counter, latch2));
playerSession3.addHandler(new SessionHandlerLatchCounter(playerSession3,
counter, latch2));
// start test
Event event1 = Events.event(null, Events.DISCONNECT);
playerSession.onEvent(event1);// disconnect session 1.
assertFalse(latch1.await(1000, TimeUnit.MILLISECONDS));// This is just a wait
Event message = Events.event(null, Events.SESSION_MESSAGE);
playerSession.onEvent(message);
assertFalse(latch1.await(500, TimeUnit.MILLISECONDS));// Ensure that the message is not sent.
Event event2 = Events.event(null, Events.DISCONNECT);
Event event3 = Events.event(null, Events.DISCONNECT);
playerSession2.onEvent(event2);
playerSession3.onEvent(event3);
assertTrue(latch2.await(500, TimeUnit.MILLISECONDS));
// 1 ondisconnect(session1) + 0 onnetwork(session1) + 2 ondisconnect(session2 and 3)
assertTrue(counter.get() == 3);
}
I overloaded onDisconnect
of class SessionHandlerLatchCounter
which extends from DefaultSessionEventHandler
and it received the events without issue. As you can see final assert is for counter to be 3 I couldn't try out an exact replica of your test, I will try to do that and let you know, but at first look there does not seem to be a bug.
Can you put break point in both DefaultSessionEventHandler
and your SessionHandler
and see why disconnect is getting invoked only on the super class and not on subclass. You will generally be able to understand by looking at which method is invoking this onDisconnect
method.
b.t.w this is the relevant code from SessionHandlerLatchCounter
@Override
public void onNetworkMessage(NetworkEvent event) {
counter.incrementAndGet();
latch.countDown();
System.out.println("invoked onNetworkMessage");
}
@Override
protected void onDisconnect(Event event)
{
counter.incrementAndGet();
latch.countDown();
System.out.println("invoked onDisconnect");
super.onDisconnect(event);
}
Hello @menacher, merge please SessionHandlerLatchCounter
changes to master branch. It fails multiSessionDisconnectValidation
test as of now.
Hi @tgregory thanks for pointing it out. I will commit this tonight. Here is the relevant code from netty4 branch(I committed in this branch and forgot to commit to master)
package org.menacheri.jetserver.util;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicLong;
import org.menacheri.jetserver.app.Session;
import org.menacheri.jetserver.event.Event;
import org.menacheri.jetserver.event.NetworkEvent;
import org.menacheri.jetserver.event.impl.DefaultSessionEventHandler;
public class SessionHandlerLatchCounter extends DefaultSessionEventHandler {
private final AtomicLong counter;
private final CountDownLatch latch;
public SessionHandlerLatchCounter(Session session, AtomicLong counter,
CountDownLatch latch) {
super(session);
this.counter = counter;
this.latch = latch;
}
@Override
public void onNetworkMessage(NetworkEvent event) {
counter.incrementAndGet();
latch.countDown();
System.out.println("invoked onNetworkMessage");
}
@Override
protected void onDisconnect(Event event)
{
counter.incrementAndGet();
latch.countDown();
System.out.println("invoked onDisconnect");
super.onDisconnect(event);
}
public AtomicLong getCounter() {
return counter;
}
public CountDownLatch getLatch() {
return latch;
}
}