This is an automated email from the ASF dual-hosted git repository.

amichair pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/aries-rsa.git

commit 41b1bbdc96d4bf06b65f12fdabd545f8e53e61e7
Author: Amichai Rothman <[email protected]>
AuthorDate: Thu May 21 09:12:44 2026 +0300

    ARIES-2228 Fix FastBinProvider socket not closed on shutdown
---
 .../rsa/provider/fastbin/FastBinProvider.java      |  7 +++-
 .../provider/fastbin/tcp/TcpTransportServer.java   | 39 ++++++++++++++++------
 2 files changed, 35 insertions(+), 11 deletions(-)

diff --git 
a/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/FastBinProvider.java
 
b/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/FastBinProvider.java
index 2962b684..16388e60 100644
--- 
a/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/FastBinProvider.java
+++ 
b/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/FastBinProvider.java
@@ -45,6 +45,7 @@ import org.apache.aries.rsa.spi.IntentUnsatisfiedException;
 import org.apache.aries.rsa.util.StringPlus;
 import org.fusesource.hawtdispatch.Dispatch;
 import org.fusesource.hawtdispatch.DispatchQueue;
+import org.fusesource.hawtdispatch.ShutdownException;
 import org.osgi.framework.BundleContext;
 import org.osgi.service.remoteserviceadmin.EndpointDescription;
 import org.osgi.service.remoteserviceadmin.RemoteConstants;
@@ -90,7 +91,11 @@ public class FastBinProvider implements DistributionProvider 
{
     }
 
     public void close() {
-        client.stop();
+        try {
+            client.stop();
+        } catch (ShutdownException se) {
+            LOG.trace("exception while shutting down client", se);
+        }
         final Semaphore counter = new Semaphore(0);
         server.stop(() -> counter.release(1));
         try {
diff --git 
a/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/tcp/TcpTransportServer.java
 
b/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/tcp/TcpTransportServer.java
index 729b53d7..6fa593a4 100644
--- 
a/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/tcp/TcpTransportServer.java
+++ 
b/provider/fastbin/src/main/java/org/apache/aries/rsa/provider/fastbin/tcp/TcpTransportServer.java
@@ -30,6 +30,8 @@ import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.SocketChannel;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.aries.rsa.provider.fastbin.io.TransportAcceptListener;
 import org.apache.aries.rsa.provider.fastbin.io.TransportServer;
@@ -163,22 +165,39 @@ public class TcpTransportServer implements 
TransportServer {
     public void stop() {
         stop(null);
     }
+
     public void stop(final Runnable onCompleted) {
         if (acceptSource.isCanceled()) {
             onCompleted.run();
         } else {
-            acceptSource.setCancelHandler(new Runnable() {
-                public void run() {
-                    try {
-                        channel.close();
-                    } catch (IOException e) {
-                    }
-                    if (onCompleted != null) {
-                        onCompleted.run();
-                    }
-                }
+            CountDownLatch latch = new CountDownLatch(1);
+            acceptSource.setCancelHandler(() -> {
+                closeChannel(onCompleted);
+                latch.countDown();
             });
             acceptSource.cancel();
+            // due to a race condition, sometimes during shutdown the hawt 
dispatcher
+            // bundle is stopped before we get here, so the handler above will 
never
+            // get executed. We give it a chance, but make sure to ultimately 
close
+            // the channel anyway to avoid leaving the socket in use.
+            try {
+                latch.await(5, TimeUnit.SECONDS);
+            } catch (InterruptedException ie) {
+                Thread.currentThread().interrupt();
+            }
+            if (channel.isOpen()) { // always close at the end
+                closeChannel(onCompleted);
+            }
+        }
+    }
+
+    private void closeChannel(Runnable onCompleted) {
+        try {
+            channel.close();
+        } catch (IOException ioe) {
+        }
+        if (onCompleted != null) {
+            onCompleted.run();
         }
     }
 

Reply via email to