Skip to content

kqueue incompatible event loop NioEventLoop #7620

@funky-eyes

Description

@funky-eyes

Check Ahead

  • I have searched the issues of this repository and believe that this is not a duplicate.

  • I am willing to try to fix this bug myself.

Ⅰ. Issue Description

seata:
  transport:
    server: native
Image
java.lang.RuntimeException: Server start failed
	at org.apache.seata.core.rpc.netty.NettyServerBootstrap.start(NettyServerBootstrap.java:210)
	at org.apache.seata.core.rpc.netty.AbstractNettyRemotingServer.init(AbstractNettyRemotingServer.java:61)
	at org.apache.seata.core.rpc.netty.NettyRemotingServer.init(NettyRemotingServer.java:63)
	at org.apache.seata.server.Server.start(Server.java:112)
	at org.apache.seata.server.ServerRunner.run(ServerRunner.java:62)
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:765)
	at org.springframework.boot.SpringApplication.lambda$callRunners$2(SpringApplication.java:749)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
	at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:744)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1289)
	at org.apache.seata.server.ServerApplication.main(ServerApplication.java:30)
Caused by: io.netty.channel.ChannelException: Unable to create Channel from class class io.netty.channel.kqueue.KQueueServerSocketChannel
	at io.netty.channel.ReflectiveChannelFactory.newChannel(ReflectiveChannelFactory.java:46)
	at io.netty.bootstrap.AbstractBootstrap.initAndRegister(AbstractBootstrap.java:326)
	at io.netty.bootstrap.AbstractBootstrap.doBind(AbstractBootstrap.java:288)
	at io.netty.bootstrap.AbstractBootstrap.bind(AbstractBootstrap.java:284)
	at io.netty.bootstrap.AbstractBootstrap.bind(AbstractBootstrap.java:262)
	at org.apache.seata.core.rpc.netty.NettyServerBootstrap.start(NettyServerBootstrap.java:196)
	... 19 common frames omitted
Caused by: java.lang.reflect.InvocationTargetException: null
	at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:74)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486)
	at io.netty.channel.ReflectiveChannelFactory.newChannel(ReflectiveChannelFactory.java:44)
	... 24 common frames omitted
Caused by: java.lang.UnsatisfiedLinkError: 'int io.netty.channel.unix.Socket.newSocketStreamFd(boolean)'
	at io.netty.channel.unix.Socket.newSocketStreamFd(Native Method)
	at io.netty.channel.unix.Socket.newSocketStream0(Socket.java:596)
	at io.netty.channel.unix.Socket.newSocketStream0(Socket.java:588)
	at io.netty.channel.kqueue.BsdSocket.newSocketStream(BsdSocket.java:197)
	at io.netty.channel.kqueue.KQueueServerSocketChannel.<init>(KQueueServerSocketChannel.java:34)
	at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
	... 27 common frames omitted
 <==

Ⅱ. Describe what happened

Because KQueueServerSocketChannel requires a KQueueEventLoopGroup to be created first so that the JNI library in netty-transport-native-kqueue can be loaded, otherwise you will get an UnsatisfiedLinkError. So the fix is to use the matching event loop group for the corresponding socket channel. Note that even if a KQueueServerSocketChannel can be instantiated (for example, you create a KQueueEventLoopGroup but don’t actually use it), it may construct successfully yet remain incompatible with a NioEventLoopGroup. For example:

   @Override
    public void start() {
        int port = getListenPort();
        new KQueueEventLoopGroup();
        this.serverBootstrap
                .group(this.eventLoopGroupBoss, this.eventLoopGroupWorker)
                .channel(NettyServerConfig.SERVER_CHANNEL_CLAZZ)
                .option(ChannelOption.SO_BACKLOG, nettyServerConfig.getSoBackLogSize())
                .option(ChannelOption.SO_REUSEADDR, true)
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childOption(ChannelOption.TCP_NODELAY, true)
                .childOption(ChannelOption.SO_SNDBUF, nettyServerConfig.getServerSocketSendBufSize())
                .childOption(ChannelOption.SO_RCVBUF, nettyServerConfig.getServerSocketResvBufSize())
                .childOption(
                        ChannelOption.WRITE_BUFFER_WATER_MARK,
                        new WriteBufferWaterMark(
                                nettyServerConfig.getWriteBufferLowWaterMark(),
                                nettyServerConfig.getWriteBufferHighWaterMark()))
                .localAddress(new InetSocketAddress(port))
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) {
                        ch.pipeline()
                                .addLast(new IdleStateHandler(nettyServerConfig.getChannelMaxReadIdleSeconds(), 0, 0))
                                .addLast(new ProtocolDetectHandler(new ProtocolDetector[] {
                                    new Http2Detector(getChannelHandlers()),
                                    new SeataDetector(getChannelHandlers()),
                                    new HttpDetector()
                                }));
                    }
                });

        try {
            this.serverBootstrap.bind(port).sync();
            LOGGER.info("Server started, service listen port: {}", getListenPort());
            Instance instance = Instance.getInstance();
            // Lines 177-180 are just for compatibility with test cases
            if (instance.getTransaction() == null) {
                Instance.getInstance().setTransaction(new Node.Endpoint(XID.getIpAddress(), XID.getPort(), "netty"));
            }
            for (RegistryService<?> registryService : MultiRegistryFactory.getInstances()) {
                registryService.register(Instance.getInstance());
            }
            initialized.set(true);
        } catch (SocketException se) {
            throw new RuntimeException("Server start failed, the listen port: " + getListenPort(), se);
        } catch (Exception exx) {
            throw new RuntimeException("Server start failed", exx);
        }
    }
Image

As shown in the screenshot, you'll then see the following new exception message:

==> 
java.lang.RuntimeException: Server start failed
	at org.apache.seata.core.rpc.netty.NettyServerBootstrap.start(NettyServerBootstrap.java:211)
	at org.apache.seata.core.rpc.netty.AbstractNettyRemotingServer.init(AbstractNettyRemotingServer.java:61)
	at org.apache.seata.core.rpc.netty.NettyRemotingServer.init(NettyRemotingServer.java:63)
	at org.apache.seata.server.Server.start(Server.java:112)
	at org.apache.seata.server.ServerRunner.run(ServerRunner.java:62)
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:765)
	at org.springframework.boot.SpringApplication.lambda$callRunners$2(SpringApplication.java:749)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
	at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:744)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1289)
	at org.apache.seata.server.ServerApplication.main(ServerApplication.java:30)
Caused by: java.lang.IllegalStateException: incompatible event loop type: io.netty.channel.nio.NioEventLoop
	at io.netty.channel.AbstractChannel$AbstractUnsafe.register(AbstractChannel.java:473)
	at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:89)
	at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:83)
	at io.netty.channel.MultithreadEventLoopGroup.register(MultithreadEventLoopGroup.java:86)
	at io.netty.bootstrap.AbstractBootstrap.initAndRegister(AbstractBootstrap.java:339)
	at io.netty.bootstrap.AbstractBootstrap.doBind(AbstractBootstrap.java:288)
	at io.netty.bootstrap.AbstractBootstrap.bind(AbstractBootstrap.java:284)
	at io.netty.bootstrap.AbstractBootstrap.bind(AbstractBootstrap.java:262)
	at org.apache.seata.core.rpc.netty.NettyServerBootstrap.start(NettyServerBootstrap.java:197)
	... 19 common frames omitted
 <==

Ⅲ. Describe what you expected to happen

No response

Ⅳ. How to reproduce it (as minimally and precisely as possible)

Add configuration

seata:
  transport:
    server: native

start server

Ⅴ. Anything else we need to know?

I don't think there's any need to provide platform-specific SocketChannel and EventLoop implementations for non‑Linux systems; non‑Linux platforms should all use the NIO implementation to avoid added maintenance and operational costs.

Ⅵ. Environment

No response

Metadata

Metadata

Assignees

Labels

type: bugCategory issues or prs related to bug.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions