Skip to content

Commit 2c3e12a

Browse files
author
oleksiys
committed
AsyncHttpClient#1067 "GrizzlyResponse object reachable from SelectorRunner thread local"
1 parent f6fd24c commit 2c3e12a

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

src/main/java/com/ning/http/client/providers/grizzly/HttpTransactionContext.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ static HttpTransactionContext cleanupTransaction(final HttpContext httpCtx) {
115115
final HttpTransactionContext httpTxContext = currentTransaction(httpCtx);
116116
if (httpTxContext != null) {
117117
httpCtx.getCloseable().removeCloseListener(httpTxContext.listener);
118+
REQUEST_STATE_ATTR.remove(httpCtx);
118119
}
119120

120121
return httpTxContext;
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright (c) 2015 Sonatype, Inc. All rights reserved.
3+
*
4+
* This program is licensed to you under the Apache License Version 2.0,
5+
* and you may not use this file except in compliance with the Apache License Version 2.0.
6+
* You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
7+
*
8+
* Unless required by applicable law or agreed to in writing,
9+
* software distributed under the Apache License Version 2.0 is distributed on an
10+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
12+
*/
13+
package com.ning.http.client.ws.grizzly;
14+
15+
import com.ning.http.client.AsyncCompletionHandler;
16+
import com.ning.http.client.AsyncHttpClient;
17+
import com.ning.http.client.AsyncHttpClientConfig;
18+
import com.ning.http.client.Response;
19+
import com.ning.http.client.providers.grizzly.GrizzlyAsyncHttpProvider;
20+
import java.lang.ref.PhantomReference;
21+
import java.lang.ref.ReferenceQueue;
22+
import java.util.concurrent.CountDownLatch;
23+
import java.util.concurrent.TimeUnit;
24+
import java.util.concurrent.atomic.AtomicReference;
25+
import static org.testng.Assert.assertTrue;
26+
import org.testng.annotations.Test;
27+
28+
/**
29+
*
30+
*/
31+
public class ResponseRefLeak {
32+
@Test
33+
public void referencedResponseHC() throws InterruptedException
34+
{
35+
AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder().build();
36+
AsyncHttpClient client = new AsyncHttpClient(new GrizzlyAsyncHttpProvider(config), config);
37+
38+
final CountDownLatch responseLatch = new CountDownLatch(1);
39+
final AtomicReference<Response> responseRef = new AtomicReference<>();
40+
41+
client.prepareGet("http://www.ning.com/").execute(new AsyncCompletionHandler<Response>()
42+
{
43+
44+
@Override
45+
public Response onCompleted(Response response) throws Exception
46+
{
47+
responseLatch.countDown();
48+
responseRef.set(response);
49+
return response;
50+
}
51+
52+
@Override
53+
public void onThrowable(Throwable t)
54+
{
55+
// Something wrong happened.
56+
}
57+
});
58+
59+
responseLatch.await(5, TimeUnit.SECONDS);
60+
verifyNotLeaked(new PhantomReference<>(responseRef.getAndSet(null), new ReferenceQueue<>()));
61+
}
62+
63+
private void verifyNotLeaked(PhantomReference possibleLeakPhantomRef) throws InterruptedException
64+
{
65+
for (int i = 0; i < 10; ++i)
66+
{
67+
System.gc();
68+
Thread.sleep(100);
69+
if (possibleLeakPhantomRef.isEnqueued())
70+
{
71+
break;
72+
}
73+
}
74+
assertTrue(possibleLeakPhantomRef.isEnqueued());
75+
}
76+
}

0 commit comments

Comments
 (0)