Those of you who have used Hibernate probably know that the connection pooling solution c3p0 comes with it.

Pity.

C3p0 has a number of default settings that Hibernate does not allow you to control directly that are downright dangerous in a production environment:

checkoutTimeout
Default: 0

The number of milliseconds a client calling getConnection() will wait for a Connection to be checked-in or acquired when the pool is exhausted. Zero means wait indefinitely. Setting any positive value will cause the getConnection() call to time-out and break with an SQLException after the specified number of milliseconds.

“Zero means wait indefinitely” — And that’s the default?! This means stuck threads if the pool ever gets exhausted due to a connection leak - with silence as your indicator that something is wrong.

unreturnedConnectionTimeout
Default: 0

Seconds. If set, if an application checks out but then fails to check-in [i.e. close()] a Connection within the specified period of time, the pool will unceremoniously destroy() the Connection. This permits applications with occasional Connection leaks to survive, rather than eventually exhausting the Connection pool. And that’s a shame. Zero means no timeout, applications are expected to close() their own Connections. Obviously, if a non-zero value is set, it should be to a value longer than any Connection should reasonably be checked-out. Otherwise, the pool will occasionally kill Connections in active use, which is bad. This is basically a bad idea, but it’s a commonly requested feature. Fix your $%!@% applications so they don’t leak Connections! Use this temporarily in combination with debugUnreturnedConnectionStackTraces to figure out where Connections are being checked-out that don’t make it back into the pool!

Here I kinda agree with what they are saying - particularly “Fix your $%!@% applications so they don’t leak Connections”. But as anyone with any practical experience with database programming knows, tracking down connection leaks is one of the more difficult bugs to resolve. This is mainly because it’s usually hard to tell how many connections have have leaked, which ones they are, where they were obtained — all critical information needed to figure out why the connection was not closed properly. And it’s difficult to think of a situation where connections should be allowed to stay out of the pool eternally…there is always some upper bound beyond which keeping a connection out of the pool is unacceptable. To default to “as long as you like” is not a sensible default.

But the real problem is the combination of these two default settings: “You can take a connection out of the pool and never return it — we don’t mind, we’ll silently trust that you meant to do that. And all the threads that are waiting for that connection to come back to the pool, well they can just wait silently forever for that connection to come back to the pool. Better cross your fingers and hope you don’t have a leak, because if you do, things will just sit there waiting silently, patiently, for the connection pool fairy to come along and fix it all. In other words, a connection leak means your system will silently hang.”

If you’re using c3p0 in a production environment, you owe it to yourself to change these settings to fit your environment. But Hibernate and c3p0 really ought not set their users up for problems like this. They should use sensible defaults (such as 30 seconds to wait for a connection, and one hour to keep it out of the pool); they should make it clear that these settings should be tuned to the environment; and they should make it easy to do so right in the Hibernate.cfg.xml file.

Leave a Reply