QPIDJMS-438 Ensure that closed sessions are removed from tracking
authorTimothy Bish <tabish121@gmail.com>
Wed, 12 Dec 2018 17:32:17 +0000 (12:32 -0500)
committerTimothy Bish <tabish121@gmail.com>
Wed, 12 Dec 2018 17:32:56 +0000 (12:32 -0500)
When a session is remotely closed it can be left in the Connection
tracking map which can lead to large leaks of remotely closed sessions
over time.  Ensure it is removed on shutdown calls.

qpid-jms-client/src/main/java/org/apache/qpid/jms/JmsSession.java

index 0970a6d..ea70544 100644 (file)
@@ -305,7 +305,6 @@ public class JmsSession implements AutoCloseable, Session, QueueSession, TopicSe
             connection.destroyResource(sessionInfo);
         } catch (JmsConnectionFailedException jmsex) {
         }
-        connection.removeSession(sessionInfo);
         if (interrupted) {
             Thread.currentThread().interrupt();
         }
@@ -328,34 +327,38 @@ public class JmsSession implements AutoCloseable, Session, QueueSession, TopicSe
 
     protected void shutdown(Throwable cause) throws JMSException {
         if (closed.compareAndSet(false, true)) {
-            sessionInfo.setState(ResourceState.CLOSED);
-            setFailureCause(cause);
-            stop();
+            try {
+                sessionInfo.setState(ResourceState.CLOSED);
+                setFailureCause(cause);
+                stop();
 
-            for (JmsMessageConsumer consumer : new ArrayList<JmsMessageConsumer>(this.consumers.values())) {
-                consumer.shutdown(cause);
-            }
+                for (JmsMessageConsumer consumer : new ArrayList<JmsMessageConsumer>(this.consumers.values())) {
+                    consumer.shutdown(cause);
+                }
 
-            for (JmsMessageProducer producer : new ArrayList<JmsMessageProducer>(this.producers.values())) {
-                producer.shutdown(cause);
-            }
+                for (JmsMessageProducer producer : new ArrayList<JmsMessageProducer>(this.producers.values())) {
+                    producer.shutdown(cause);
+                }
 
-            transactionContext.shutdown();
+                transactionContext.shutdown();
 
-            // Ensure that no asynchronous completion sends remain blocked after close.
-            synchronized (sessionInfo) {
-                if (cause == null) {
-                    cause = new JMSException("Session closed remotely before message transfer result was notified");
-                }
+                // Ensure that no asynchronous completion sends remain blocked after close.
+                synchronized (sessionInfo) {
+                    if (cause == null) {
+                        cause = new JMSException("Session closed remotely before message transfer result was notified");
+                    }
 
-                getCompletionExecutor().execute(new FailOrCompleteAsyncCompletionsTask(JmsExceptionSupport.create(cause)));
-                getCompletionExecutor().shutdown();
-            }
+                    getCompletionExecutor().execute(new FailOrCompleteAsyncCompletionsTask(JmsExceptionSupport.create(cause)));
+                    getCompletionExecutor().shutdown();
+                }
 
-            try {
-                getCompletionExecutor().awaitTermination(connection.getCloseTimeout(), TimeUnit.MILLISECONDS);
-            } catch (InterruptedException e) {
-                LOG.trace("Session close awaiting send completions was interrupted");
+                try {
+                    getCompletionExecutor().awaitTermination(connection.getCloseTimeout(), TimeUnit.MILLISECONDS);
+                } catch (InterruptedException e) {
+                    LOG.trace("Session close awaiting send completions was interrupted");
+                }
+            } finally {
+                connection.removeSession(sessionInfo);
             }
         }
     }