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
[Bug] Jdbi3-core - connection object can be stuck in a connection pool forever if connection was closed. #2446
Comments
Thank you for the very detailed bug report. We'll take a look at this as soon as we can. |
Right now, we check if a connection is closed before closing it. However, this isn't good enough: even if the server closed the connection, we might have borrowed this from a pool, which needs to know we've returned it. Connection.close is specified to no-op if called more than once, so it's safe to just do it regardless. Fixes #2446
Right now, we check if a connection is closed before closing it. However, this isn't good enough: even if the server closed the connection, we might have borrowed this from a pool, which needs to know we've returned it. Connection.close is specified to no-op if called more than once, so it's safe to just do it regardless. Fixes #2446
Hi @kristoffSC , I have proposed a change that closes the connection without first checking to see if it is already closed in #2451. Could you see if this fixes the problem for you? |
Hi Thanks for looking at this issue. |
Hi @stevenschlansker The generalization is that if there will be an exception thrown anywhere in I would say that Specific use cases:
In this case, since exception was thrown from Handle constructor, there is no Handle instance to close/clean at the end.
This will throw an exception for PostgresPlugin. To reproduce this, please pull my repository (I added PostgresPlugin) and simply restart Postgresql container on a break point just after where connection object is acquired from the pool. The PoC patch for this could be something like this:
|
Right now, we check if a connection is closed before closing it. Also, if a plugin fails to customize a Handle, the connection can leak However, this isn't good enough: even if the server closed the connection, we might have borrowed this from a pool, which needs to know we've returned it. Connection.close is specified to no-op if called more than once, so it's safe to just do it regardless. Fixes #2446
Right now, we check if a connection is closed before closing it. Also, if a plugin fails to customize a Handle, the connection can leak However, this isn't good enough: even if the server closed the connection, we might have borrowed this from a pool, which needs to know we've returned it. Connection.close is specified to no-op if called more than once, so it's safe to just do it regardless. Fixes #2446
OK, I agree if a |
Right now, we check if a connection is closed before closing it. Also, if a plugin fails to customize a Handle, the connection can leak However, this isn't good enough: even if the server closed the connection, we might have borrowed this from a pool, which needs to know we've returned it. Connection.close is specified to no-op if called more than once, so it's safe to just do it regardless. Fixes #2446
Right now, we check if a connection is closed before closing it. Also, if a plugin fails to customize a Handle, the connection can leak However, this isn't good enough: even if the server closed the connection, we might have borrowed this from a pool, which needs to know we've returned it. Connection.close is specified to no-op if called more than once, so it's safe to just do it regardless. Fixes #2446
Right now, we check if a connection is closed before closing it. Also, if a plugin fails to customize a Handle, the connection can leak However, this isn't good enough: even if the server closed the connection, we might have borrowed this from a pool, which needs to know we've returned it. Connection.close is specified to no-op if called more than once, so it's safe to just do it regardless. Fixes #2446
Right now, we check if a connection is closed before closing it. Also, if a plugin fails to customize a Handle, the connection can leak However, this isn't good enough: even if the server closed the connection, we might have borrowed this from a pool, which needs to know we've returned it. Connection.close is specified to no-op if called more than once, so it's safe to just do it regardless. Fixes #2446
Right now, we check if a connection is closed before closing it. Also, if a plugin fails to customize a Handle, the connection can leak However, this isn't good enough: even if the server closed the connection, we might have borrowed this from a pool, which needs to know we've returned it. Connection.close is specified to no-op if called more than once, so it's safe to just do it regardless. Fixes #2446
Right now, we check if a connection is closed before closing it. Also, if a plugin fails to customize a Handle, the connection can leak However, this isn't good enough: even if the server closed the connection, we might have borrowed this from a pool, which needs to know we've returned it. Connection.close is specified to no-op if called more than once, so it's safe to just do it regardless. Fixes #2446
If the c'tor of a handle throws an exception, ensure that the underlying connection is closed as the caller will not have a chance to do so with try-with-resources This fixes the cause of jdbi#2446
If the c'tor of a handle throws an exception, ensure that the underlying connection is closed as the caller will not have a chance to do so with try-with-resources This fixes the cause of jdbi#2446
If the c'tor of a handle throws an exception, ensure that the underlying connection is closed as the caller will not have a chance to do so with try-with-resources This fixes the cause of jdbi#2446
If the c'tor of a handle throws an exception, ensure that the underlying connection is closed as the caller will not have a chance to do so with try-with-resources This fixes the cause of jdbi#2446
Right now, we check if a connection is closed before closing it. Also, if a plugin fails to customize a Handle, the connection can leak However, this isn't good enough: even if the server closed the connection, we might have borrowed this from a pool, which needs to know we've returned it. Connection.close is specified to no-op if called more than once, so it's safe to just do it regardless. Fixes jdbi#2446
If the c'tor of a handle throws an exception, ensure that the underlying connection is closed as the caller will not have a chance to do so with try-with-resources This fixes the cause of jdbi#2446
The issue has been fixed by #2458 Tested using reproducer from this bug report. |
I cut a 3.41.0-rc1 release which should hit central soon. As this bug fix is a major part of this release, please test with the 3.41.0-rc1 and lmk if that works for you. |
Hi, |
Hi,
it seems that
jdbi3-core
might have a code path that can make broken connection objects stuck in the connection pool forever in "ALLOCATED" state. This can lead to max out the connection pool capacity. This is what most likely have happen in our system.I have created a reproducer for this issue with detailed instructions - here
In Handle's constructor there is a check, that verifies if used connection for this handle is live. The Cleanable is added to the created Handle instance ONLY if connection is Live.
If the connection was closed or had any connection issue (client or server side) after it was borrowed from the pool and before this check, then no Cleanable will be registered making this connection object never be returned to the pool.
###### UPDATE ######
After deeper analysis it seems that problem is more complex.
The generalization is that if there will be an exception thrown anywhere in
org.jdbi.v3.core.Jdbi::open()
method, after the connection was acquired from pool, then the connection object will not be returned to the pool.I would say that
org.jdbi.v3.core.Jdbi::open()
should have exception handling logic which will guaranty that connection object will be properly returned to the pool in case of exception. Currently it is not the case.Specific use cases:
In this case it turns out that exception will be thrown by this line in Handle's constructor.
this.transactionHandler = transactionHandler.specialize(this);
so even before registering any Cleanable objectsIn this case, since exception was thrown from Handle constructor, there is no Handle instance to close/clean at the end.
In our system we are using Jdbi's PostgresPlugin. In
org.jdbi.v3.core.Jdbi::open()
method, after Handle object is created there is this call:This will throw an exception for PostgresPlugin.
In result the
open()
method will not return any Handle reference so no Handle will be closed/clean up hence connection object will not be returned to the pool. The stack trace for this case -JdbiTrace.txt
To reproduce this, please pull my repository (I added PostgresPlugin) and simply restart Postgresql container on a break point just after where connection object is acquired from the pool.
The PoC patch for this could be something like this:
The text was updated successfully, but these errors were encountered: