Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,16 @@
import io.netty.incubator.channel.uring.IOUringSocketChannel;
import io.netty.resolver.dns.DnsNameResolver;
import io.netty.resolver.dns.DnsNameResolverBuilder;
import io.netty.util.concurrent.DefaultThreadFactory;
import java.net.*;
import java.util.concurrent.ThreadFactory;

public class TcpClientSession extends TcpSession {
private static final String IP_REGEX = "\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b";
private static Class<? extends Channel> CHANNEL_CLASS;
private static Class<? extends DatagramChannel> DATAGRAM_CHANNEL_CLASS;
private static EventLoopGroup EVENT_LOOP_GROUP;
private static final int WAIT_FOR_SHUTDOWN_IN_MS = 2000;

private final String bindAddress;
private final int bindPort;
Expand Down Expand Up @@ -295,27 +298,37 @@ private static void createTcpEventLoopGroup() {

switch (TransportHelper.determineTransportMethod()) {
case IO_URING:
EVENT_LOOP_GROUP = new IOUringEventLoopGroup();
EVENT_LOOP_GROUP = new IOUringEventLoopGroup(newThreadFactory());
CHANNEL_CLASS = IOUringSocketChannel.class;
DATAGRAM_CHANNEL_CLASS = IOUringDatagramChannel.class;
break;
case EPOLL:
EVENT_LOOP_GROUP = new EpollEventLoopGroup();
EVENT_LOOP_GROUP = new EpollEventLoopGroup(newThreadFactory());
CHANNEL_CLASS = EpollSocketChannel.class;
DATAGRAM_CHANNEL_CLASS = EpollDatagramChannel.class;
break;
case KQUEUE:
EVENT_LOOP_GROUP = new KQueueEventLoopGroup();
EVENT_LOOP_GROUP = new KQueueEventLoopGroup(newThreadFactory());
CHANNEL_CLASS = KQueueSocketChannel.class;
DATAGRAM_CHANNEL_CLASS = KQueueDatagramChannel.class;
break;
case NIO:
EVENT_LOOP_GROUP = new NioEventLoopGroup();
EVENT_LOOP_GROUP = new NioEventLoopGroup(newThreadFactory());
CHANNEL_CLASS = NioSocketChannel.class;
DATAGRAM_CHANNEL_CLASS = NioDatagramChannel.class;
break;
}

Runtime.getRuntime().addShutdownHook(new Thread(() -> EVENT_LOOP_GROUP.shutdownGracefully()));
Runtime.getRuntime().addShutdownHook(new Thread(() -> EVENT_LOOP_GROUP.shutdownGracefully().awaitUninterruptibly(WAIT_FOR_SHUTDOWN_IN_MS)));
}

protected static ThreadFactory newThreadFactory() {
// Create a new daemon thread. When the last non daemon thread ends
// the runtime environment will call the shutdown hooks. One of the
// hooks will try to shut down the event loop group which will
// normally lead to the thread exiting. If not, it will be forcably
// killed after WAIT_FOR_SHUTDOWN_IN_MS ms along with the other
// daemon threads as the runtime exits.
return new DefaultThreadFactory(TcpClientSession.class, true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutException;
import io.netty.handler.timeout.WriteTimeoutHandler;
import io.netty.util.concurrent.DefaultThreadFactory;
import net.kyori.adventure.text.Component;

import javax.annotation.Nullable;
Expand All @@ -32,6 +33,7 @@ public abstract class TcpSession extends SimpleChannelInboundHandler<Packet> imp
*/
public static boolean USE_EVENT_LOOP_FOR_PACKETS = true;
private static EventLoopGroup PACKET_EVENT_LOOP;
private static final int WAIT_FOR_SHUTDOWN_IN_MS = 2000;

protected String host;
protected int port;
Expand Down Expand Up @@ -296,7 +298,10 @@ public void disconnect(final Component reason, final Throwable cause) {
}

if (PACKET_EVENT_LOOP == null) {
PACKET_EVENT_LOOP = new DefaultEventLoopGroup();
// See TcpClientSession.newThreadFactory() for details on
// daemon threads and their interaction with the runtime.
PACKET_EVENT_LOOP = new DefaultEventLoopGroup(new DefaultThreadFactory(this.getClass(), true));
Runtime.getRuntime().addShutdownHook(new Thread(() -> PACKET_EVENT_LOOP.shutdownGracefully().awaitUninterruptibly(WAIT_FOR_SHUTDOWN_IN_MS)));
}
return PACKET_EVENT_LOOP.next();
}
Expand Down