fix(networking): Prevent hanging the network loop if an exception occurs

This commit is contained in:
KingRainbow44 2024-07-06 22:54:10 -04:00
parent af70de316e
commit e7ed66477f
No known key found for this signature in database
GPG Key ID: FC2CB64B00D257BE
2 changed files with 18 additions and 3 deletions

View File

@ -2,6 +2,7 @@ package emu.grasscutter.net.impl;
import emu.grasscutter.net.INetworkTransport; import emu.grasscutter.net.INetworkTransport;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.utils.Utils;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.channel.DefaultEventLoop; import io.netty.channel.DefaultEventLoop;
import io.netty.channel.EventLoop; import io.netty.channel.EventLoop;
@ -83,11 +84,20 @@ public class NetworkTransportImpl extends KcpServer implements INetworkTransport
return; return;
} }
transport.networkLoop.submit(() -> session.onReceived(byteBuf.array())); // Copy the buffer to avoid reference issues.
var data = Utils.byteBufToArray(byteBuf);
transport.networkLoop.submit(() -> {
// Fun fact: if we don't catch exceptions here,
// we run the risk of locking the entire network loop.
try {
session.onReceived(data);
} catch (Exception ex) {
session.getLogger().warn("Unable to handle received data.", ex);
}
});
} catch (Exception ex) { } catch (Exception ex) {
NetworkTransportImpl.log.warn("Unable to handle received data.", ex); NetworkTransportImpl.log.warn("Unable to handle received data.", ex);
} finally {
byteBuf.release();
} }
} }

View File

@ -14,6 +14,7 @@ import emu.grasscutter.utils.*;
import io.netty.buffer.*; import io.netty.buffer.*;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import lombok.*; import lombok.*;
import org.slf4j.Logger;
public class GameSession implements IGameSession { public class GameSession implements IGameSession {
@Getter private final GameServer server; @Getter private final GameServer server;
@ -49,6 +50,10 @@ public class GameSession implements IGameSession {
return this.session.getAddress(); return this.session.getAddress();
} }
public Logger getLogger() {
return this.session.getLogger();
}
public synchronized void setPlayer(Player player) { public synchronized void setPlayer(Player player) {
this.player = player; this.player = player;
this.player.setSession(this); this.player.setSession(this);