plc4x
plc4x copied to clipboard
[Bug]: SerialSocketChannel does not properly close itself
What happened?
For some reason, if Bootstrap.connect(...)
had failed for any reason, EventLoopGroup.shutdownGracefullly does not close channel and keeps select
-ing it indefinitely, causing a lot of logs to appear
NioEventLoop -- Selector.select() returned prematurely 512 times in a row; rebuilding Selector org.apache.plc4x.java.transport.serial.SerialPollingSelector@5bb67f2.
NioEventLoop -- Migrated 1 channel(s) to the new Selector.
NioEventLoop -- Selector.select() returned prematurely 512 times in a row; rebuilding Selector org.apache.plc4x.java.transport.serial.SerialPollingSelector@4a67eb86.
NioEventLoop -- Migrated 1 channel(s) to the new Selector.
NioEventLoop -- Selector.select() returned prematurely 512 times in a row; rebuilding Selector org.apache.plc4x.java.transport.serial.SerialPollingSelector@748a37b5.
NioEventLoop -- Migrated 1 channel(s) to the new Selector.
There is a basic repro - it purposely tries to open non-existent serial port and fails: https://gist.github.com/zawodskoj/68987f535bbfe199eeee9be43cf4bf13
There is also a dirty workaround - it is possible to obtain SerialPollingSelector through reflection and invoke close()
on them, catching meaningless NotImplementedException
val getJCh = AbstractNioChannel::class.java.getDeclaredMethod("javaChannel")
getJCh.isAccessible = true
val javach = getJCh.invoke(cch) as AbstractInterruptibleChannel
try {
javach.close()
} catch (e: NotImplementedException) {
// ???
}
Soon after another rebuildSelector0()
, Netty attempts to re-register channel, fails to do so (because it is already closed) and exits the infinite loop
WARN io.netty.channel.nio.NioEventLoop -- Selector.select() returned prematurely 512 times in a row; rebuilding Selector org.apache.plc4x.java.transport.serial.SerialPollingSelector@287d3f58.
WARN io.netty.channel.nio.NioEventLoop -- Failed to re-register a Channel to the new Selector.
java.nio.channels.ClosedChannelException: null
at java.base/java.nio.channels.spi.AbstractSelectableChannel.register(AbstractSelectableChannel.java:222)
at io.netty.channel.nio.NioEventLoop.rebuildSelector0(NioEventLoop.java:467)
at io.netty.channel.nio.NioEventLoop.rebuildSelector(NioEventLoop.java:368)
at io.netty.channel.nio.NioEventLoop.unexpectedSelectorWakeup(NioEventLoop.java:630)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:578)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:840)
INFO io.netty.channel.nio.NioEventLoop -- Migrated 0 channel(s) to the new Selector.
Version
v0.11.0
Programming Languages
- [X] plc4j
- [ ] plc4go
- [ ] plc4c
- [ ] plc4net
Protocols
- [ ] AB-Ethernet
- [ ] ADS /AMS
- [ ] BACnet/IP
- [ ] CANopen
- [ ] DeltaV
- [ ] DF1
- [ ] EtherNet/IP
- [ ] Firmata
- [ ] KNXnet/IP
- [ ] Modbus
- [ ] OPC-UA
- [ ] S7