Skip to content

Commit e1169ee

Browse files
committed
Fix for Bug#99260 (31189960), statement.setQueryTimeout,creates a database connection and does not close.
1 parent 05778ef commit e1169ee

File tree

3 files changed

+62
-12
lines changed

3 files changed

+62
-12
lines changed

CHANGES

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
Version 8.0.28
55

6+
- Fix for Bug#99260 (31189960), statement.setQueryTimeout,creates a database connection and does not close.
7+
68
- Fix for Bug#103324 (32770013), X DevAPI Collection.replaceOne() missing matching _id check.
79

810
- Fix for Bug#105197 (33461744), Statement.executeQuery() may return non-navigable ResultSet.

src/main/core-impl/java/com/mysql/cj/CancelQueryTaskImpl.java

+20-12
Original file line numberDiff line numberDiff line change
@@ -91,24 +91,32 @@ public void run() {
9191
String user = hostInfo.getUser();
9292
String password = hostInfo.getPassword();
9393

94-
NativeSession newSession = new NativeSession(hostInfo, session.getPropertySet());
95-
newSession.connect(hostInfo, user, password, database, 30000, new TransactionEventHandler() {
96-
@Override
97-
public void transactionCompleted() {
94+
NativeSession newSession = null;
95+
try {
96+
newSession = new NativeSession(hostInfo, session.getPropertySet());
97+
newSession.connect(hostInfo, user, password, database, 30000, new TransactionEventHandler() {
98+
@Override
99+
public void transactionCompleted() {
100+
}
101+
102+
public void transactionBegun() {
103+
}
104+
});
105+
newSession.sendCommand(new NativeMessageBuilder(newSession.getServerSession().supportsQueryAttributes())
106+
.buildComQuery(newSession.getSharedSendPacket(), "KILL QUERY " + origConnId), false, 0);
107+
} finally {
108+
try {
109+
newSession.forceClose();
110+
} catch (Throwable t) {
111+
// no-op.
98112
}
99-
100-
public void transactionBegun() {
101-
}
102-
});
103-
newSession.sendCommand(new NativeMessageBuilder(newSession.getServerSession().supportsQueryAttributes())
104-
.buildComQuery(newSession.getSharedSendPacket(), "KILL QUERY " + origConnId), false, 0);
105-
113+
}
106114
localQueryToCancel.setCancelStatus(CancelStatus.CANCELED_BY_TIMEOUT);
107115
}
108116
}
109117
// } catch (NullPointerException npe) {
110118
// Case when connection closed while starting to cancel.
111-
// We can't easily synchronise this, because then one thread can't cancel() a running query.
119+
// We can't easily synchronize this, because then one thread can't cancel() a running query.
112120
// Ignore, we shouldn't re-throw this, because the connection's already closed, so the statement has been timed out.
113121
} catch (Throwable t) {
114122
CancelQueryTaskImpl.this.caughtWhileCancelling = t;

src/test/java/testsuite/regression/StatementRegressionTest.java

+40
Original file line numberDiff line numberDiff line change
@@ -11940,4 +11940,44 @@ public void testBug96900() throws Exception {
1194011940
assertEquals(0, this.rs.getInt(1));
1194111941
}
1194211942

11943+
/**
11944+
* Tests fix for Bug#99260 (31189960), statement.setQueryTimeout,creates a database connection and does not close.
11945+
*
11946+
* @throws Exception
11947+
*/
11948+
@Test
11949+
public void testBug99260() throws Exception {
11950+
Supplier<Integer> sessionCount = () -> {
11951+
try {
11952+
this.stmt.execute("FLUSH STATUS");
11953+
this.rs = this.stmt.executeQuery("SHOW STATUS LIKE 'threads_connected'");
11954+
this.rs.next();
11955+
return this.rs.getInt(2);
11956+
} catch (SQLException e) {
11957+
throw new RuntimeException(e.getMessage(), e);
11958+
}
11959+
};
11960+
11961+
int initialSessionCount = sessionCount.get();
11962+
11963+
Properties props = new Properties();
11964+
props.setProperty(PropertyKey.sslMode.getKeyName(), SslMode.DISABLED.name());
11965+
props.setProperty(PropertyKey.allowPublicKeyRetrieval.getKeyName(), "true");
11966+
11967+
Connection testConn = getConnectionWithProps(props);
11968+
Statement testStmt = testConn.createStatement();
11969+
11970+
testStmt.setQueryTimeout(1);
11971+
for (int i = 0; i < 5; i++) {
11972+
assertThrows(MySQLTimeoutException.class, "Statement cancelled due to timeout or client request", () -> {
11973+
testStmt.executeQuery("SELECT SLEEP(30)");
11974+
return null;
11975+
});
11976+
// The difference between the `initialSessionCount` and the current session count would be greater than one if connections external to this test are
11977+
// created in between. Chances for this to happen in a controlled or development environment are very low and can be neglected.
11978+
assertEquals(1, sessionCount.get() - initialSessionCount);
11979+
}
11980+
11981+
testConn.close();
11982+
}
1194311983
}

0 commit comments

Comments
 (0)