Fixed potential race condition in case of abnormal termination of pipelined message exchange (request producers / response consumers may be not fully closed out)

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpasyncclient/trunk@1631168 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/AbstractClientExchangeHandler.java b/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/AbstractClientExchangeHandler.java
index 0d22b85..c437c40 100644
--- a/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/AbstractClientExchangeHandler.java
+++ b/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/AbstractClientExchangeHandler.java
@@ -402,13 +402,16 @@
 
     @Override
     public final void failed(final Exception ex) {
-        try {
-            executionFailed(ex);
-        } finally {
+        if (this.closed.compareAndSet(false, true)) {
             try {
-                this.resultFuture.failed(ex);
+                try {
+                    executionFailed(ex);
+                } finally {
+                    discardConnection();
+                    releaseResources();
+                }
             } finally {
-                close();
+                this.resultFuture.failed(ex);
             }
         }
     }
@@ -423,11 +426,11 @@
                 try {
                     return executionCancelled();
                 } finally {
-                    this.resultFuture.cancel();
+                    discardConnection();
+                    releaseResources();
                 }
             } finally {
-                discardConnection();
-                releaseResources();
+                this.resultFuture.cancel();
             }
         }
         return false;
diff --git a/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/PipeliningClientExchangeHandlerImpl.java b/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/PipeliningClientExchangeHandlerImpl.java
index 994c9a9..8b06a38 100644
--- a/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/PipeliningClientExchangeHandlerImpl.java
+++ b/httpasyncclient/src/main/java/org/apache/http/impl/nio/client/PipeliningClientExchangeHandlerImpl.java
@@ -153,6 +153,9 @@
         if (responseConsumer != null) {
             responseConsumer.failed(ex);
         }
+        for (final HttpAsyncResponseConsumer<T> cancellable: this.responseConsumerQueue) {
+            cancellable.cancel();
+        }
     }
 
     @Override
@@ -296,7 +299,7 @@
             if (result != null) {
                 this.resultQueue.add(result);
             } else {
-                this.resultFuture.failed(ex);
+                failed(ex);
             }
             if (!this.resultFuture.isDone() && this.responseConsumerQueue.isEmpty()) {
                 this.resultFuture.completed(new ArrayList<T>(this.resultQueue));
diff --git a/httpasyncclient/src/test/java/org/apache/http/nio/client/integration/TestHttpAsyncPipelining.java b/httpasyncclient/src/test/java/org/apache/http/nio/client/integration/TestHttpAsyncPipelining.java
index c13b699..80830d7 100644
--- a/httpasyncclient/src/test/java/org/apache/http/nio/client/integration/TestHttpAsyncPipelining.java
+++ b/httpasyncclient/src/test/java/org/apache/http/nio/client/integration/TestHttpAsyncPipelining.java
@@ -216,9 +216,9 @@
         Assert.assertNotNull(c1.getResult());
         Assert.assertTrue(c2.isDone());
         Assert.assertNotNull(c2.getResult());
-        Assert.assertFalse(c3.isDone());
+        Assert.assertTrue(c3.isDone());
         Assert.assertNull(c3.getResult());
-        Assert.assertFalse(c4.isDone());
+        Assert.assertTrue(c4.isDone());
         Assert.assertNull(c4.getResult());
     }