Bug 56660 - Resource leak in FairBlockingQueue::poll method
Summary: Resource leak in FairBlockingQueue::poll method
Status: RESOLVED DUPLICATE of bug 53367
Alias: None
Product: Tomcat Modules
Classification: Unclassified
Component: jdbc-pool (show other bugs)
Version: unspecified
Hardware: All All
: P2 major (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-06-23 22:05 UTC by Alexander Pogrebnyak
Modified: 2015-06-04 17:12 UTC (History)
1 user (show)



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Alexander Pogrebnyak 2014-06-23 22:05:40 UTC
tomcat-jdbc version: 7.0.54

In this code fragment from FairBlockingQueue::poll method

                Line 144
                //the queue is empty we will wait for an object
                ExchangeCountDownLatch<E> c = new ExchangeCountDownLatch<E>(1);
                //add to the bottom of the wait list
                waiters.addLast(c);
                //unlock the global lock
                lock.unlock();
                //wait for the specified timeout
                if (!c.await(timeout, unit)) {
                    //if we timed out, remove ourselves from the waitlist
                    lock.lock();
                    waiters.remove(c);
                    lock.unlock();
                }
                //return the item we received, can be null if we timed out
                result = c.getItem();

When the 'c.await' is interrupted, the Latch is not removed from 'waiters'.
As I understand, it can hold on to the connection object.

Thus the pool is leaking connections, and at some time, all new requests just hang on the c.await indefinitely.

The fix is pretty simple. Catch InterruptedException (and any other non-checked exception) and do a cleanup there.

    boolean needsWaitersCleanup = false;
    
    try
    {
        if (!c.await(timeout, unit)) {
            needsWaitersCleanup = true;
        }
    }
    catch ( InterruptedException | RuntimeException | Error e )
    {
        needsWaitersCleanup = true;
    
        throw e;
    }
    finally
    {
        if ( needsWaitersCleanup )
        {
            //if we timed out, remove ourselves from the waitlist
            lock.lock();
            try
            {
                waiters.remove(c);
            }
            finally
            {
                lock.unlock();
            }
        }
    }
Comment 1 Alexander Pogrebnyak 2014-06-23 22:09:17 UTC
I've encountered this bug in production, under a heavy load.  The problem here is that it's manifestation is pretty random.

One workaround, until this bug is fixed, is to turn off 'fairQueue' property of PoolProperties.

When 'fairQueue' is off, current implementation falls back to 'java.util.concurrent.ArrayBlockingQueue', which does not have this issue.
Comment 2 Filip Hanik 2015-06-04 17:12:21 UTC
https://issues.apache.org/bugzilla/show_bug.cgi?id=53367

*** This bug has been marked as a duplicate of bug 53367 ***