Repository navigation
LDEV-6503 (6.2) discard timed-out connections instead of returning them to the pool - #2854
Closed
GianTschingt wants to merge 1 commit into
Closed
GianTschingt wants to merge 1 commit into
GianTschingt wants to merge 1 commit into
Conversation
…the pool (6.2) - DatasourceManagerImpl.releaseConnection() invalidates the connection in the pool instead of release() when the thread is interrupted or the request timed out; a request timeout can stop the driver in the middle of reading a response and the next borrower would get that unread result - the pool accounting from LDEV-5966 is kept, the connection is destroyed through the pool - backports the invalidate() helper (LDEV-6129) and DatasourceConnectionImpl.getPool() from 7.0 - test/tickets/LDEV6503.cfc
Contributor
Author
|
Closing this one. By default fixes go into 7.1 only, see #2853. We can still backport later if it's needed. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Jira: https://luceeserver.atlassian.net/browse/LDEV-6503
Forum report: https://dev.lucee.org/t/17621
Problem
Since LDEV-5966 (
3417970d4, 6.2.5.6 / 7.0.2.10)DatasourceManagerImpl.releaseConnection()always returns the connection to the pool withrelease(). Before that, a connection used by a timed-out request was closed. The idea was that validation on the next borrow catches a bad connection. But withvalidate=false(the default)validateObject()only checksisClosed()and the idle/live timeout.On 6.2 and 7.0 a request timeout interrupts the thread and then calls
Thread.stop(). TheThreadDeathhits as soon as the driver's socket read returns, so the response is left half read on the connection. The connection goes back to the pool and the next request that borrows it gets the result of the timed-out query instead of its own. On a server-level datasource that can be another application or user.Fix
Same change as the 7.0 PR (6.2 is no longer merged into 7.0, so this is its own PR). In
releaseConnection(), if the current thread is interrupted, or the request (ThreadLocalPageContext.get(pc)) has timed out (getTimeoutStackTrace() != null), the connection is invalidated in the pool with a privateinvalidate(dc)helper instead ofrelease(). The connection is destroyed through commons-pool2 (invalidateObject()), so the pool counters stay right and the LDEV-5966 fix is kept. One change in one place:Query,QueryLazy,Insert/Update,StoredProc,DBInfoand the transactionend()path all release through this method.6.2 doesn't have LDEV-6129 yet, so this backports its
invalidate(dc)helper (with the 6.2DatasourceConnectionProcasts) andDatasourceConnectionImpl.getPool()unchanged from 7.0. No classloader changes, no new exception wrapping. Apart from that it reusesThreadLocalPageContext.get()andPageContextImpl.getTimeoutStackTrace().Trade-off
cfthread action="terminate"(thereSystemUtil.stop()gets no PageContext, so no timeout stack trace is set).Thread.stop()is gone) the query may have finished cleanly before the release. The connection is still discarded, so it's one reconnect per timed-out request, like before 6.2.5.6.Test
test/tickets/LDEV6503.cfc(labelspostgres,datasource, skipped when no Postgres datasource is configured; CI has one). It uses a datasource withvalidate=false, recordspg_backend_pid(), then runs acfthreadwithrequesttimeout=1andpg_sleep(5)that returnsA_MARKER,A_ID. After that it asserts:PID), not the timed-out request's result (fails without the fix on Java < 20);Repro summary
The forum repro (request A in a
cfthreadwithrequesttimeout=3, then request B on the same datasource), PostgreSQL 17, bundled pgjdbc,validate=false, 6 runs each:A_MARKER,A_ID)validate=trueon the datasource avoided the swap in all runs.Local verification
The changed classes were compiled from this branch (
javac --release 11) into the 6.2.9.4-RC jar (the branch base is that RC plus the version bump).LDEV6503.cfcwas run with script-runner against a local PostgreSQL 17:Expected [PID] Actual [A_MARKER,A_ID]Opened by Gian Tschingt, Lucee community assistant for Michael Offner.