Julian, thank you so much for your attention on this. Your code changes
look good but unfortunately I am still experiencing the problem.
Here is some log output from my program. You can see that the close is
called on the DefaultNettyPlcConnection, but I do not see the output from
your code modification that I would expect if the closeEventLoopForChannel
method was being called (Either logger.info("Channel is closed, closing
worker Group also") or logger.warn("Trying to remove EventLoop for Channel
{} but have none stored", channel).
The nioEventLoopGroup threads continue to persist after every
plcConnection.
I hope I have built everything correctly...I checked out your branch with:
git clone --single-branch --branch bugfix/close-eventloop-after-channel
https://github.com/apache/plc4x.git
And wiped out my local m2 maven repository before building the code with:
./mvnw install -DskipTests
I also removed references to the apache snapshot repo from my project pom
and by all appearances I am using the correct 0.8.0-SNAPSHOT jars that are
locally built in my local m2 repo. Here is some log info from my test:
2020-08-24_10:15:43.450 DEBUG PooledPlcDriverManager - Try to borrow an
object for url modbus://192.168.0.5:503?unit-identifier=50
2020-08-24_10:15:43.452 INFO TcpChannelFactory - Configuring Bootstrap
with Configuration{}
2020-08-24_10:15:43.458 DEBUG ModbusManager - Connection Metadata:
2020-08-24_10:15:43.459 DEBUG ModbusManager -
org.apache.plc4x.java.spi.connection.DefaultNettyPlcConnection@185c140
2020-08-24_10:15:43.462 DEBUG Plc4xNettyWrapper - Forwarding request to plc
ModbusTcpADU[transactionIdentifier=10,unitIdentifier=50,pdu=ModbusPDUReadHoldingRegistersRequest[startingAddress=67,quantity=1]]
2020-08-24_10:15:43.466 DEBUG GeneratedDriverByteToMessageCodec - Sending
bytes to PLC for message
ModbusTcpADU[transactionIdentifier=10,unitIdentifier=50,pdu=ModbusPDUReadHoldingRegistersRequest[startingAddress=67,quantity=1]]
as data 000a00000006320300430001
2020-08-24_10:15:43.470 DEBUG Plc4xNettyWrapper - Forwarding request to plc
ModbusTcpADU[transactionIdentifier=11,unitIdentifier=50,pdu=ModbusPDUReadHoldingRegistersRequest[startingAddress=69,quantity=1]]
2020-08-24_10:15:43.471 DEBUG GeneratedDriverByteToMessageCodec - Sending
bytes to PLC for message
ModbusTcpADU[transactionIdentifier=11,unitIdentifier=50,pdu=ModbusPDUReadHoldingRegistersRequest[startingAddress=69,quantity=1]]
as data 000b00000006320300450001
2020-08-24_10:15:43.480 DEBUG Plc4xNettyWrapper - Forwarding request to plc
ModbusTcpADU[transactionIdentifier=12,unitIdentifier=50,pdu=ModbusPDUReadHoldingRegistersRequest[startingAddress=68,quantity=1]]
2020-08-24_10:15:43.481 DEBUG GeneratedDriverByteToMessageCodec - Sending
bytes to PLC for message
ModbusTcpADU[transactionIdentifier=12,unitIdentifier=50,pdu=ModbusPDUReadHoldingRegistersRequest[startingAddress=68,quantity=1]]
as data 000c00000006320300440001
2020-08-24_10:15:43.484 DEBUG Plc4xNettyWrapper - Forwarding request to plc
ModbusTcpADU[transactionIdentifier=13,unitIdentifier=50,pdu=ModbusPDUReadHoldingRegistersRequest[startingAddress=66,quantity=1]]
2020-08-24_10:15:43.485 DEBUG GeneratedDriverByteToMessageCodec - Sending
bytes to PLC for message
ModbusTcpADU[transactionIdentifier=13,unitIdentifier=50,pdu=ModbusPDUReadHoldingRegistersRequest[startingAddress=66,quantity=1]]
as data 000d00000006320300420001
2020-08-24_10:15:43.489 DEBUG PooledPlcDriverManager - close called on
org.apache.plc4x.java.spi.connection.DefaultNettyPlcConnection@185c140
2020-08-24_10:15:43.490 INFO ReadModbusTask - Read Modbus Task Completed.
Some details from my code:
Getting the connection:
PlcConnection plcConnection =
pooledDriverManager.getConnection(modbusServerURI);
if (plcConnection.isConnected()) {
LOG.trace("The connection is connected");
} else {
LOG.trace("The connection is not connected. Connecting
now...");
plcConnection.connect();
}
Reading the plc and closing the connection:
PlcReadRequest.Builder builder = plcConnection.readRequestBuilder();
builder.addItem("devicename", "holding-register:1[8]");
builder.addItem("generatorstate", "holding-register:67");
builder.addItem("batteryvoltage", "holding-register:513[2]");
builder.addItem("batterycurrent", "holding-register:515[2]");
builder.addItem("pvpowerwatts", "holding-register:69[2]");
builder.addItem("pvinputthishourkwh", "holding-register:307[2]");
PlcReadRequest readRequest = builder.build();
PlcReadResponse response;
try {
response = readRequest.execute().get(5, TimeUnit.SECONDS);
//process response
catch (InterruptedException | ExecutionException | TimeoutException ex) {
LOG.error("Error in executing gateway read - interrupted or
timed out", ex);
}
} finally {
plcConnection.close();
} catch (Exception ex) {
LOG.error("Error closing modbus connection", ex);
}
}
Other details:
openjdk version: "13.0.2" 2020-01-15
Linux Version:
PRETTY_NAME="Raspbian GNU/Linux 10 (buster)"
NAME="Raspbian GNU/Linux"
VERSION="10 (buster)"
On Mon, Aug 24, 2020 at 4:39 AM Julian Feinauer <
[email protected]> wrote:
> Hi,
>
> short feedback. I looked into the code and indeed it seems that we had a
> bug there which could lead tot he socket leak you described.
> I pushed a fix in the branch:
>
> https://github.com/apache/plc4x/tree/bugfix/close-eventloop-after-channel
>
> Would you mind taking a look and testing this with your code @Adam Rossi?
>
> Thanks!
> Juliasn
>
> Am 24.08.20, 08:26 schrieb "Julian Feinauer" <
> [email protected]>:
>
> Perhaps, some related questions:
>
> - You are using Linux for your Tests?
> - Do you close all Connections properly?
> Normally the `PlcConnection.close()` method should close the EventLoop.
>
> Julian
>
> Am 24.08.20, 08:23 schrieb "Julian Feinauer" <
> [email protected]>:
>
> Hi Adam,
>
> I will have a look today!
>
> Do we have a Jira Issue for it already?
>
> Julian
>
> Am 24.08.20, 07:38 schrieb "Christofer Dutz" <
> [email protected]>:
>
> Hi Adam,
>
> of course that's unfortunate ... also I will not be able to
> address this issue soon as I have to work on the tasks of my research
> project.
> I have one more month to work on this and I'm months behind
> schedule because I have been doing free support way too much lately.
>
> I really hope Julian will be able to help ... he's way more
> into the details of Netty than I am (cause he's got the book ;-) )
>
> So Julian? ... it would be super awesome if you could take on
> this issue.
>
> Chris
>
>
>
> Am 24.08.20, 00:17 schrieb "Adam Rossi" <[email protected]>:
>
> Thanks, I did test with 0.8.0-SNAPSHOT and see the same
> behavior. In every
> plcConnection a nioEventLoopGroup thread is created and
> does not ever seem
> to be destroyed.
>
> I wish I understood the io.netty.channel.EventLoopGroup
> class better to be
> more helpful here. Would an example program that
> reproduces this thread
> leak be useful?
>
> jconsole shows the thread data as:
>
> Name: nioEventLoopGroup-19-1
> State: RUNNABLE
> Total blocked: 0 Total waited: 0
>
> Stack trace:
> [email protected]/sun.nio.ch.EPoll.wait(Native Method)
> [email protected]
>
> /sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:120)
> [email protected]
>
> /sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:124)
> - locked
> io.netty.channel.nio.SelectedSelectionKeySet@1838f97
> - locked sun.nio.ch.EPollSelectorImpl@1f49287
> [email protected]/sun.nio.ch
> .SelectorImpl.select(SelectorImpl.java:141)
>
> app//io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:68)
>
> app//io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:803)
>
> app//io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:457)
>
> app//io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
>
> app//io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
>
> app//io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
> [email protected]/java.lang.Thread.run(Thread.java:830)
>
>
> Regards, Adam
>
> On Sun, Aug 23, 2020 at 1:00 PM Christofer Dutz <
> [email protected]>
> wrote:
>
> > Hi Adam,
> >
> > the Apache SNAPSHOT repo is at:
> >
> https://repository.apache.org/content/repositories/snapshots
> >
> > Adding this to your pom should help:
> >
> > <!-- Make Snapshots of Apache projects available -->
> > <repositories>
> > <repository>
> > <id>apache-snapshots</id>
> > <url>
> https://repository.apache.org/content/repositories/snapshots
> > </url>
> > <releases>
> > <enabled>false</enabled>
> > </releases>
> > <snapshots>
> > <enabled>true</enabled>
> > </snapshots>
> > </repository>
> > </repositories>
> >
> > <!-- Make Snapshots of Apache plugins available -->
> > <pluginRepositories>
> > <pluginRepository>
> > <id>apache-snapshots</id>
> > <url>
> https://repository.apache.org/content/repositories/snapshots
> > </url>
> > <releases>
> > <enabled>false</enabled>
> > </releases>
> > <snapshots>
> > <enabled>true</enabled>
> > </snapshots>
> > </pluginRepository>
> > </pluginRepositories>
> >
> > Chris
> > Am 23.08.20, 18:56 schrieb "Adam Rossi" <
> [email protected]>:
> >
> > Sure thing. Is 0.8.0-snapshot hosted anywhere or is
> that something
> > that needs to be built? Regards Adam
> >
> > > On Aug 23, 2020, at 12:31 PM, Christofer Dutz <
> > [email protected]> wrote:
> > >
> > > Hmm ...
> > >
> > > Could you possibly give 0.8.0-SNAPSHOT a try? ....
> or 0.6.x? ...
> > 0.7.0 was the first of the new generation drivers. We're
> maintaining the
> > 0.6 branch and working hard on making the new generation
> drivers 100%
> > production ready.
> > >
> > > Chris
> > >
> > >
> > > Am 23.08.20, 18:06 schrieb "Adam Rossi" <
> [email protected]>:
> > >
> > > This is the latest 0.7.0 release from Maven.
> > >
> > >
> > > Regards Adam
> > >
> > >> On Aug 23, 2020, at 11:56 AM, Christofer Dutz <
> > [email protected]> wrote:
> > >>
> > >> Hi Adam,
> > >>
> > >> which version of PLC4X are you using? I know we
> had similar reports
> > some time ago, but had thought we had fixed them
> > >>
> > >> Chris
> > >>
> > >>
> > >>
> > >> Am 23.08.20, 16:40 schrieb "Adam Rossi" <
> [email protected]>:
> > >>
> > >> Howdy. I am seeing a persistent thread being
> created for every
> > >> plcConnection connect which looks like the
> following:
> > >>
> > >> Name: nioEventLoopGroup-11-1
> > >> State: RUNNABLE
> > >> Total blocked: 0 Total waited: 0
> > >>
> > >> Stack trace:
> > >> [email protected]/sun.nio.ch.EPoll.wait(Native
> Method)
> > >> [email protected]
> > >>
> /sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:120)
> > >> [email protected]
> > >>
> /sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:124)
> > >> - locked
> io.netty.channel.nio.SelectedSelectionKeySet@f6df6b
> > >> - locked sun.nio.ch.EPollSelectorImpl@7ffc19
> > >> [email protected]/sun.nio.ch
> > .SelectorImpl.select(SelectorImpl.java:141)
> > >>
> >
> app//io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:68)
> > >>
> >
> app//io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:803)
> > >>
> app//io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:457)
> > >>
> >
> app//io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
> > >>
> >
> app//io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
> > >>
> >
> app//io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
> > >> [email protected]
> /java.lang.Thread.run(Thread.java:830)
> > >>
> > >>
> > >> This happens both when creating a connection
> directly or when
> > using the
> > >> plc4x connection pool.
> > >>
> > >> In both cases I am obtaining the connection,
> reading some modbus
> > values,
> > >> and then closing the connection. From the
> plcConnection metadata
> > the
> > >> connection type I am using is:
> > >>
> > >>
> org.apache.plc4x.java.spi.connection.DefaultNettyPlcConnection
> > >>
> > >> Over time thousands of these nioEventLoopGroup
> threads are
> > created and I
> > >> experience an OutOfMemory error in my program.
> > >>
> > >> Has anyone experienced this problem? Is there a
> way to force
> > these threads
> > >> to close, timeout, or to specify the total
> thread limit?
> > >>
> > >> Thanks and Regards, Adam
> > >>
> > >
> >
> >
>
>
>
>
>