You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by jf...@apache.org on 2020/08/24 07:48:35 UTC
[plc4x] 01/01: Bugfix EventLoop is not closed when Connection is
closed and thus can leak.
This is an automated email from the ASF dual-hosted git repository.
jfeinauer pushed a commit to branch bugfix/close-eventloop-after-channel
in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit 5691692061b524c98ae38ce5c00ac73e5ec3e132
Author: julian <j....@pragmaticminds.de>
AuthorDate: Mon Aug 24 09:48:26 2020 +0200
Bugfix EventLoop is not closed when Connection is closed and thus can leak.
---
.../plc4x/java/spi/connection/ChannelFactory.java | 5 ++++-
.../spi/connection/DefaultNettyPlcConnection.java | 4 ++++
.../java/spi/connection/NettyChannelFactory.java | 20 ++++++++++++++++++++
3 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/ChannelFactory.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/ChannelFactory.java
index 82d0b1f..cc96082 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/ChannelFactory.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/ChannelFactory.java
@@ -34,6 +34,9 @@ public interface ChannelFactory {
// Intentionally do Nothing
}
- //void ping() throws PlcException;
+ default void closeEventLoopForChannel(Channel channel) {
+ // By default do nothing for compatibility
+ // Extending classes should implement their logic here
+ }
}
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/DefaultNettyPlcConnection.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/DefaultNettyPlcConnection.java
index ce43c73..117728b 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/DefaultNettyPlcConnection.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/DefaultNettyPlcConnection.java
@@ -132,6 +132,10 @@ public class DefaultNettyPlcConnection extends AbstractPlcConnection implements
channel.pipeline().fireUserEventTriggered(new CloseConnectionEvent());
// Close channel
channel.close().awaitUninterruptibly();
+
+ // Shutdown the Worker Group
+ channelFactory.closeEventLoopForChannel(channel);
+
channel = null;
connected = false;
}
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/NettyChannelFactory.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/NettyChannelFactory.java
index f07b88a..823fcd1 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/NettyChannelFactory.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/NettyChannelFactory.java
@@ -30,7 +30,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.SocketAddress;
+import java.util.Map;
import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
/**
* Adapter with sensible defaults for a Netty Based Channel Factory.
@@ -43,6 +45,8 @@ public abstract class NettyChannelFactory implements ChannelFactory {
private static final Logger logger = LoggerFactory.getLogger(NettyChannelFactory.class);
private static final int PING_TIMEOUT_MS = 1_000;
+ private final Map<Channel, EventLoopGroup> eventLoops = new ConcurrentHashMap<>();
+
/**
* TODO should be removed together with the Constructor.
*/
@@ -115,6 +119,9 @@ public abstract class NettyChannelFactory implements ChannelFactory {
final Channel channel = f.channel();
+ // Add to Event Loop Group
+ eventLoops.put(channel, workerGroup);
+
// It seems the embedded channel operates differently.
// Intentionally using the class name as we don't want to require a
// hard dependency on the test-channel.
@@ -134,6 +141,19 @@ public abstract class NettyChannelFactory implements ChannelFactory {
}
}
+ @Override
+ public void closeEventLoopForChannel(Channel channel) {
+ if (eventLoops.containsKey(channel)) {
+ logger.info("Channel is closed, closing worker Group also");
+ EventLoopGroup eventExecutors = eventLoops.get(channel);
+ eventLoops.remove(channel);
+ eventExecutors.shutdownGracefully().awaitUninterruptibly();
+ logger.info("Worker Group was closed successfully!");
+ } else {
+ logger.warn("Trying to remove EventLoop for Channel {} but have none stored", channel);
+ }
+ }
+
// TODO do we want to keep this like that?
/*@Override
public void ping() throws PlcException {