Skip to content

GrizzlyResponse object reachable from SelectorRunner thread local #1067

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
elrodro83 opened this issue Dec 22, 2015 · 8 comments
Closed

GrizzlyResponse object reachable from SelectorRunner thread local #1067

elrodro83 opened this issue Dec 22, 2015 · 8 comments
Assignees
Milestone

Comments

@elrodro83
Copy link

Hi,

We are using grizzly through AHC to perform some HTTP requests. After those requests have finished, in a thread dump i can still see the response objects being referenced, and not being garbage collected. Attached is a screenshot of there references from a heap dump:

screen shot 2015-12-22 at 9 37 37 am

In a case where the size of the transferred data is big, i see some heavy memory usage.

The problem seems to be with the reference chain TCPNIOConnection -> IndexedAttributeHolder -> $Snapshot -> HttpTransactionContext. Perhaps at least one of those references should be discarded after the request has completed, or provide a way to an app to clear that.

The following test can reproduce this issue.

    @Test
    public void referencedResponseHC() throws InterruptedException
    {
        AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder().build();
        AsyncHttpClient client = new AsyncHttpClient(new GrizzlyAsyncHttpProvider(config), config);

        final CountDownLatch responseLatch = new CountDownLatch(1);
        final AtomicReference<Response> responseRef = new AtomicReference<>();

        client.prepareGet("http://www.ning.com/").execute(new AsyncCompletionHandler<Response>()
        {

            @Override
            public Response onCompleted(Response response) throws Exception
            {
                responseLatch.countDown();
                responseRef.set(response);
                return response;
            }

            @Override
            public void onThrowable(Throwable t)
            {
                // Something wrong happened.
            }
        });

        responseLatch.await(5, TimeUnit.SECONDS);
        verifyNotLeaked(new PhantomReference<>(responseRef.getAndSet(null), new ReferenceQueue<>()));
    }

    private void verifyNotLeaked(PhantomReference possibleLeakPhantomRef) throws InterruptedException
    {
        for (int i = 0; i < 10; ++i)
        {
            System.gc();
            Thread.sleep(100);
            if (possibleLeakPhantomRef.isEnqueued())
            {
                break;
            }
        }
        assertTrue(possibleLeakPhantomRef.isEnqueued());
    }

Thanks in advance,

@elrodro83
Copy link
Author

Just in case, this situation doesn't happen when using grizzly alone (without AHC)

@slandelle
Copy link
Contributor

Just being curious, can you reproduce such leak with the Netty provider?

@elrodro83
Copy link
Author

Hi,

Switching to the netty provider there is no reference to the response, the given test is ok in that case.

@slandelle
Copy link
Contributor

Thanks for your feedback.
Assigning to Alexei, there isn't much I can do on the Grizzly side.

@oleksiys
Copy link
Contributor

@elrodro83 thank you! I'll take a look asap

oleksiys pushed a commit that referenced this issue Dec 23, 2015
#1067
"GrizzlyResponse object reachable from SelectorRunner thread local"
@oleksiys
Copy link
Contributor

pls. check if the fix works for you.

@elrodro83
Copy link
Author

Worked like a charm!

@slandelle slandelle added this to the 1.9.32 milestone Jan 14, 2016
@slandelle
Copy link
Contributor

This fix was shipped with 1.9.32 that's already out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants