C3P0ConnectionProvider not getting closed on SessionFactory.close

Description

The C3P0 connection pool does not get closed (and cleaned up) when the session factory is closed. This results in a memory leak when the app is undeployed/redeployed. Adding this bit of code (eg to a ServletContextListener.contextDestroyed) solves the issue:

private void closeSessionFactory(SessionFactory factory) {
if(factory instanceof SessionFactoryImpl) {
SessionFactoryImpl sf = (SessionFactoryImpl)factory;
ConnectionProvider conn = sf.getConnectionProvider();
if(conn instanceof C3P0ConnectionProvider) {
((C3P0ConnectionProvider)conn).close();
}
}
factory.close();
}

Activity

Steve EbersoleMarch 20, 2014 at 7:55 PM

See the comments (and commits) on HHH-8923. The issue is fixed, but there is a question about how to best backport that (since it required an SPI change).

Steve EbersoleMarch 20, 2014 at 2:08 PM

As mentioned on HHH-8896, this is the result of an open design question wrt HIbernate's ServiceRegistry. See for details.

Claudio CarlenzoliJanuary 5, 2014 at 6:23 AM
Edited

I've tried the suggested code in a J2EE Application Server Context (in particular Tomcat 7) and I've noticed this message

Tomcat Log

Looking in the source code of c3p0 (version 0.9.1 but in version 0.9.2.1 is always the same..) I've found an explanation

From com.mchange.v2.resourcepool.BasicResourcePool - part of method close(boolean)

com.mchange.v2.resourcepool.BasicResourcePool.java

I discovered that a part of procedure is performed by a Thread and this ends up with the SEVERE message reported.
In an environment of ServletContext redeploy I prefer to avoid this error message so I just add a

Thread.sleep(2000) //2 sec

statement to the suggested code just to give time to the close procedure.

workaround

It is a "not-normal" workaround but works...

Vernon WoodwardJanuary 22, 2013 at 5:56 PM

I am also experiencing this issue. If an application starts and stops within a JVM, the session pool stays open, even though the instantiating threads have stopped. By staying open the session pool does not release the database (using postgres) connections.

I generally see two threads, one of which is:
Daemon Thread [com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1]

Shawn ClowaterNovember 19, 2012 at 7:18 PM
Edited

I've also observed this behavior. By not calling close on the pool it leaves at least one background timer thread running holding a reference to the pool itself.

IIRC, I had tracked it down to the root cause of when the service registry is destroyed in the SessionFactory close it doesn't walk up the chain destroying the parents.

From AbstractServiceRegistryImpl

This only works on the direct serviceBindingList and doesn't destroy any of the parent services.

Duplicate

Details

Assignee

Reporter

Labels

Components

Affects versions

Priority

Created June 4, 2012 at 8:22 AM
Updated March 24, 2014 at 8:22 PM
Resolved March 24, 2014 at 8:22 PM