[ 
https://issues.apache.org/jira/browse/AMQ-5258?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Sergiy Barlabanov updated AMQ-5258:
-----------------------------------

    Description: 
org.apache.activemq.jms.pool.PooledConnectionFactory creates a connection on 
startup without giving it back to the pool:

{code:java}
    public void start() {
        LOG.debug("Staring the PooledConnectionFactory: create on start = {}", 
isCreateConnectionOnStartup());
        stopped.set(false);
        if (isCreateConnectionOnStartup()) {
            try {
                // warm the pool by creating a connection during startup
                createConnection();
            } catch (JMSException e) {
                LOG.warn("Create pooled connection during start failed. This 
exception will be ignored.", e);
            }
        }
    }
{code}

So no close() method of PooledConnection is called and so no 
decrementReferenceCount is called on ConnectionPool. So referenceCount never 
becomes 0.
Later on if an exception occurs and hasExpired of ConnectionPool is set to 
true, the connection will not be closed since expiredCheck() method of 
ConnectionPool always compares referenceCount with 0 and does close() only if 
it is 0.

So we have a dead ConnectionPool instance and all usages result in "XXX closed" 
errors.

The fix would be to add call to close() just after doing createConnection() in 
PooledConnectionFactory#start() to make referenceCount go to 0. Something like 
this:

{code:java}
    public void start() {
        LOG.debug("Staring the PooledConnectionFactory: create on start = {}", 
isCreateConnectionOnStartup());
        stopped.set(false);
        if (isCreateConnectionOnStartup()) {
            try {
                // warm the pool by creating a connection during startup
                createConnection().close(); // <--- makes sure referenceCount 
goes to 0
            } catch (JMSException e) {
                LOG.warn("Create pooled connection during start failed. This 
exception will be ignored.", e);
            }
        }
    }
{code}

  was:
org.apache.activemq.jms.pool.PooledConnectionFactory creates a connection on 
startup without giving it back to the pool. So no close() method of 
PooledConnection is called and so no decrementReferenceCount is called on 
ConnectionPool. So referenceCount never becomes 0.
Later on if an exception occurs and hasExpired of ConnectionPool is set to 
true, the connection will not be closed since expiredCheck of ConnectionPool 
compares referenceCount with 0 and does close() only if it is 0.
So we have a dead ConnectionPool instance and all usages result in "XXX closed" 
errors.

The fix would be to add call to close() just after doing createConnection() in 
PooledConnectionFactory#start() to make referenceCount go to 0. Something like 
this:

{code:java}
    public void start() {
        LOG.debug("Staring the PooledConnectionFactory: create on start = {}", 
isCreateConnectionOnStartup());
        stopped.set(false);
        if (isCreateConnectionOnStartup()) {
            try {
                // warm the pool by creating a connection during startup
                createConnection().close(); // <--- makes sure referenceCount 
goes to 0
            } catch (JMSException e) {
                LOG.warn("Create pooled connection during start failed. This 
exception will be ignored.", e);
            }
        }
    }
{code}


> Connection reference leak in PooledConnectionFactory leading to expired 
> connections stuck in the pool
> -----------------------------------------------------------------------------------------------------
>
>                 Key: AMQ-5258
>                 URL: https://issues.apache.org/jira/browse/AMQ-5258
>             Project: ActiveMQ
>          Issue Type: Bug
>          Components: activemq-pool
>    Affects Versions: 5.9.1, 5.10.0
>            Reporter: Sergiy Barlabanov
>
> org.apache.activemq.jms.pool.PooledConnectionFactory creates a connection on 
> startup without giving it back to the pool:
> {code:java}
>     public void start() {
>         LOG.debug("Staring the PooledConnectionFactory: create on start = 
> {}", isCreateConnectionOnStartup());
>         stopped.set(false);
>         if (isCreateConnectionOnStartup()) {
>             try {
>                 // warm the pool by creating a connection during startup
>                 createConnection();
>             } catch (JMSException e) {
>                 LOG.warn("Create pooled connection during start failed. This 
> exception will be ignored.", e);
>             }
>         }
>     }
> {code}
> So no close() method of PooledConnection is called and so no 
> decrementReferenceCount is called on ConnectionPool. So referenceCount never 
> becomes 0.
> Later on if an exception occurs and hasExpired of ConnectionPool is set to 
> true, the connection will not be closed since expiredCheck() method of 
> ConnectionPool always compares referenceCount with 0 and does close() only if 
> it is 0.
> So we have a dead ConnectionPool instance and all usages result in "XXX 
> closed" errors.
> The fix would be to add call to close() just after doing createConnection() 
> in PooledConnectionFactory#start() to make referenceCount go to 0. Something 
> like this:
> {code:java}
>     public void start() {
>         LOG.debug("Staring the PooledConnectionFactory: create on start = 
> {}", isCreateConnectionOnStartup());
>         stopped.set(false);
>         if (isCreateConnectionOnStartup()) {
>             try {
>                 // warm the pool by creating a connection during startup
>                 createConnection().close(); // <--- makes sure referenceCount 
> goes to 0
>             } catch (JMSException e) {
>                 LOG.warn("Create pooled connection during start failed. This 
> exception will be ignored.", e);
>             }
>         }
>     }
> {code}



--
This message was sent by Atlassian JIRA
(v6.2#6252)

Reply via email to