HTTPCORE-345: EntityAsyncContentProducer fails to release resources allocated by the underlying entity when #produceContent is never invoked Contributed by Tad Whitenight <tadwhitenight at gmail.com git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpcore/branches/4.2.x@1499262 13f79535-47bb-0310-9956-ffa450edef68 Project: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/repo Commit: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/commit/6c66e1e6 Tree: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/tree/6c66e1e6 Diff: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/diff/6c66e1e6 Branch: refs/heads/4.2.x Commit: 6c66e1e6215b66b80b25886031f634c0c3d0e0ca Parents: b27fc70 Author: Oleg Kalnichevski <ol...@apache.org> Authored: Wed Jul 3 08:41:05 2013 +0000 Committer: Oleg Kalnichevski <ol...@apache.org> Committed: Wed Jul 3 08:41:05 2013 +0000 ---------------------------------------------------------------------- RELEASE_NOTES.txt | 4 ++++ .../http/nio/entity/EntityAsyncContentProducer.java | 5 +++++ .../TestHttpAsyncPrematureTermination.java | 15 ++++++++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/6c66e1e6/RELEASE_NOTES.txt ---------------------------------------------------------------------- diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 0338632..50c60ea 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,6 +1,10 @@ Changes since Release 4.2.4 ------------------- +* [HTTPCORE-345] EntityAsyncContentProducer fails to release resources allocated by the underlying + entity when #produceContent is never invoked. + Contributed by Tad Whitenight <tadwhitenight at gmail.com> + * Non-blocking connection pool to avoid scanning the entire queue of pending connection requests on each connection lease / release operation (under heavy load the request queue can contain a significant number of pending requests, a full linear scan of which can cause massive http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/6c66e1e6/httpcore-nio/src/main/java/org/apache/http/nio/entity/EntityAsyncContentProducer.java ---------------------------------------------------------------------- diff --git a/httpcore-nio/src/main/java/org/apache/http/nio/entity/EntityAsyncContentProducer.java b/httpcore-nio/src/main/java/org/apache/http/nio/entity/EntityAsyncContentProducer.java index 35d0cf0..ea25c38 100644 --- a/httpcore-nio/src/main/java/org/apache/http/nio/entity/EntityAsyncContentProducer.java +++ b/httpcore-nio/src/main/java/org/apache/http/nio/entity/EntityAsyncContentProducer.java @@ -28,6 +28,7 @@ package org.apache.http.nio.entity; import java.io.IOException; +import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; @@ -86,6 +87,10 @@ public class EntityAsyncContentProducer implements HttpAsyncContentProducer { if (local != null) { local.close(); } + if (this.entity.isStreaming()) { + InputStream instream = this.entity.getContent(); + instream.close(); + } } } http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/6c66e1e6/httpcore-nio/src/test/java/org/apache/http/nio/integration/TestHttpAsyncPrematureTermination.java ---------------------------------------------------------------------- diff --git a/httpcore-nio/src/test/java/org/apache/http/nio/integration/TestHttpAsyncPrematureTermination.java b/httpcore-nio/src/test/java/org/apache/http/nio/integration/TestHttpAsyncPrematureTermination.java index 2865bde..5ae6919 100644 --- a/httpcore-nio/src/test/java/org/apache/http/nio/integration/TestHttpAsyncPrematureTermination.java +++ b/httpcore-nio/src/test/java/org/apache/http/nio/integration/TestHttpAsyncPrematureTermination.java @@ -26,11 +26,14 @@ */ package org.apache.http.nio.integration; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.net.InetSocketAddress; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import org.apache.http.Consts; import org.apache.http.HttpConnection; import org.apache.http.HttpCoreNIOTestBase; import org.apache.http.HttpException; @@ -41,6 +44,7 @@ import org.apache.http.LoggingClientConnectionFactory; import org.apache.http.LoggingServerConnectionFactory; import org.apache.http.concurrent.FutureCallback; import org.apache.http.entity.ContentType; +import org.apache.http.entity.InputStreamEntity; import org.apache.http.impl.DefaultConnectionReuseStrategy; import org.apache.http.impl.DefaultHttpResponseFactory; import org.apache.http.impl.nio.DefaultNHttpClientConnection; @@ -178,6 +182,14 @@ public class TestHttpAsyncPrematureTermination extends HttpCoreNIOTestBase { @Test public void testConnectionTerminatedHandlingRequest() throws Exception { + final CountDownLatch responseStreamClosed = new CountDownLatch(1); + final InputStream testInputStream = new ByteArrayInputStream("all is well".getBytes(Consts.ASCII)) { + @Override + public void close() throws IOException { + responseStreamClosed.countDown(); + super.close(); + } + }; HttpAsyncRequestHandlerRegistry registry = new HttpAsyncRequestHandlerRegistry(); registry.register("*", new HttpAsyncRequestHandler<HttpRequest>() { @@ -195,7 +207,7 @@ public class TestHttpAsyncPrematureTermination extends HttpCoreNIOTestBase { ExecutionContext.HTTP_CONNECTION); conn.shutdown(); HttpResponse response = httpExchange.getResponse(); - response.setEntity(new NStringEntity("all is well", ContentType.TEXT_PLAIN)); + response.setEntity(new InputStreamEntity(testInputStream, -1)); httpExchange.submitResponse(); } @@ -229,6 +241,7 @@ public class TestHttpAsyncPrematureTermination extends HttpCoreNIOTestBase { this.connpool, context, callback); Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); + Assert.assertTrue(responseStreamClosed.await(5, TimeUnit.SECONDS)); } @Test