This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 93ef7b6a080fa9fc86a08e9ace74d44976feec99 Author: opencode <[email protected]> AuthorDate: Thu Nov 5 15:23:04 2026 +0100 Do not book queries into a released statistics store SlowQueryReport.getQueryStats() read the cached queries map directly and did not consult the store's released flag. After close(false), a connection still borrowed by the application therefore kept recording query statistics into a store that the name view and the remaining MBean already read as absent. Check PoolStatistics.isReleased() before booking and take the existing lost-store path. Add a test that closes the pool with a connection still borrowed and asserts getQueryStats() returns null. --- .../jdbc/pool/interceptor/SlowQueryReport.java | 6 ++++++ ...estSlowQueryReportSlowLogAfterChainRelease.java | 25 ++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java index 054d16c85a..576b99905e 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java @@ -542,6 +542,12 @@ public class SlowQueryReport extends AbstractQueryReport { sql = ""; } ConcurrentHashMap<String, QueryStats> queries = SlowQueryReport.this.queries; + PoolStatistics own = SlowQueryReport.this.poolStatistics; + if (own != null && own.isReleased()) { + // The pool closed while this session was still borrowed, so the + // store is no longer observable: do not book into it. + queries = null; + } if (queries == null) { if (reportClosedOrAbandoned() && log.isWarnEnabled()) { log.warn(MessageFactory.get("slowQueryReport.connectionClosedOrAbandoned")); diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestSlowQueryReportSlowLogAfterChainRelease.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestSlowQueryReportSlowLogAfterChainRelease.java index 5c1e363eaa..7564854c38 100644 --- a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestSlowQueryReportSlowLogAfterChainRelease.java +++ b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestSlowQueryReportSlowLogAfterChainRelease.java @@ -136,6 +136,31 @@ class TestSlowQueryReportSlowLogAfterChainRelease extends JdbcPoolBaseTest { } } + @Test + void aBorrowedConnectionDoesNotBookIntoAReleasedStore() throws Exception { + String poolName = "SlowLogReleasedStore-" + System.nanoTime(); + DataSource ds = newDataSource(); + ds.setName(poolName); + ds.setJdbcInterceptors(SlowQueryReport.class.getName() + "(threshold=0)"); + ds.getPoolProperties().setInitialSize(0); + + Connection con = ds.getConnection(); + SlowQueryReport report = interceptorOf(con, SlowQueryReport.class); + Assertions.assertNotNull(report, "the chain must hold the report instance"); + try { + // close(false) leaves this borrowed session alive but releases + // the pool's statistics store. + ds.close(false); + Assertions.assertNull(SlowQueryReport.getPoolStats(poolName), + "precondition: the closed pool has released its store"); + + Assertions.assertNull(report.getQueryStats("SELECT released-store"), + "a session left alive by close(false) must not book into the released store"); + } finally { + con.close(); + } + } + @Test void slowQueryWarnsAndNotifiesTogetherWhenTheStatisticsCannotBeResolved() throws Exception { String poolName = "SlowLogChannels-" + System.nanoTime(); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
