Skip to content

Commit

Permalink
Fix for Bug#29329326, PLEASE AVOID SHOW PROCESSLIST IF POSSIBLE.
Browse files Browse the repository at this point in the history
  • Loading branch information
soklakov committed Feb 25, 2019
1 parent a8aed8b commit 2e350a5
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 26 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

Version 8.0.16

- Fix for Bug#29329326, PLEASE AVOID SHOW PROCESSLIST IF POSSIBLE.

- WL#12460, DevAPI: Support new session reset functionality.

- WL#12459, DevAPI: Support connection-attributes.
Expand Down
42 changes: 20 additions & 22 deletions src/main/core-api/java/com/mysql/cj/protocol/SocketMetadata.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 2.0, as published by the
Expand Down Expand Up @@ -51,38 +51,36 @@ default boolean isLocallyConnected(Session sess, String processHost) {
int endIndex = processHost.lastIndexOf(":");
if (endIndex != -1) {
processHost = processHost.substring(0, endIndex);
}

try {
try {

InetAddress[] whereMysqlThinksIConnectedFrom = InetAddress.getAllByName(processHost);
InetAddress[] whereMysqlThinksIConnectedFrom = InetAddress.getAllByName(processHost);

SocketAddress remoteSocketAddr = sess.getRemoteSocketAddress();
SocketAddress remoteSocketAddr = sess.getRemoteSocketAddress();

if (remoteSocketAddr instanceof InetSocketAddress) {
InetAddress whereIConnectedTo = ((InetSocketAddress) remoteSocketAddr).getAddress();
if (remoteSocketAddr instanceof InetSocketAddress) {
InetAddress whereIConnectedTo = ((InetSocketAddress) remoteSocketAddr).getAddress();

for (InetAddress hostAddr : whereMysqlThinksIConnectedFrom) {
if (hostAddr.equals(whereIConnectedTo)) {
sess.getLog().logDebug(Messages.getString("SocketMetadata.1", new Object[] { hostAddr, whereIConnectedTo }));
return true;
}
sess.getLog().logDebug(Messages.getString("SocketMetadata.2", new Object[] { hostAddr, whereIConnectedTo }));
for (InetAddress hostAddr : whereMysqlThinksIConnectedFrom) {
if (hostAddr.equals(whereIConnectedTo)) {
sess.getLog().logDebug(Messages.getString("SocketMetadata.1", new Object[] { hostAddr, whereIConnectedTo }));
return true;
}

} else {
sess.getLog().logDebug(Messages.getString("SocketMetadata.3", new Object[] { remoteSocketAddr }));
sess.getLog().logDebug(Messages.getString("SocketMetadata.2", new Object[] { hostAddr, whereIConnectedTo }));
}

return false;
} catch (UnknownHostException e) {
sess.getLog().logWarn(Messages.getString("Connection.CantDetectLocalConnect", new Object[] { processHost }), e);

return false;
} else {
sess.getLog().logDebug(Messages.getString("SocketMetadata.3", new Object[] { remoteSocketAddr }));
}

return false;
} catch (UnknownHostException e) {
sess.getLog().logWarn(Messages.getString("Connection.CantDetectLocalConnect", new Object[] { processHost }), e);

return false;
}
sess.getLog().logWarn(Messages.getString("SocketMetadata.4", new Object[] { processHost }));
return false;

}

return false;
Expand Down
17 changes: 14 additions & 3 deletions src/main/core-impl/java/com/mysql/cj/NativeSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -530,8 +530,9 @@ public boolean configureClientCharacterSet(boolean dontCheckServerMatch) {

this.characterEncoding.setValue(realJavaEncoding);
} /* not utf-8 */else {
String mysqlCharsetName = connectionCollationSuffix.length() > 0 ? connectionCollationCharset : CharsetMapping
.getMysqlCharsetForJavaEncoding(realJavaEncoding.toUpperCase(Locale.ENGLISH), getServerSession().getServerVersion());
String mysqlCharsetName = connectionCollationSuffix.length() > 0 ? connectionCollationCharset
: CharsetMapping.getMysqlCharsetForJavaEncoding(realJavaEncoding.toUpperCase(Locale.ENGLISH),
getServerSession().getServerVersion());

if (mysqlCharsetName != null) {

Expand Down Expand Up @@ -815,6 +816,7 @@ public void loadServerVariables(Object syncMutex, String version) {
queryBuf.append(", @@lower_case_table_names AS lower_case_table_names");
queryBuf.append(", @@max_allowed_packet AS max_allowed_packet");
queryBuf.append(", @@net_write_timeout AS net_write_timeout");
queryBuf.append(", @@performance_schema AS performance_schema");
if (!versionMeetsMinimum(8, 0, 3)) {
queryBuf.append(", @@query_cache_size AS query_cache_size");
queryBuf.append(", @@query_cache_type AS query_cache_type");
Expand Down Expand Up @@ -1045,7 +1047,16 @@ private String findProcessHost(long threadId) {
try {
String processHost = null;

NativePacketPayload resultPacket = sendCommand(this.commandBuilder.buildComQuery(null, "SHOW PROCESSLIST"), false, 0);
String ps = this.protocol.getServerSession().getServerVariable("performance_schema");

NativePacketPayload resultPacket = versionMeetsMinimum(5, 6, 0) // performance_schema.threads in MySQL 5.5 does not contain PROCESSLIST_HOST column
&& ps != null && ("1".contentEquals(ps) || "ON".contentEquals(ps))
? sendCommand(this.commandBuilder.buildComQuery(null,
"select PROCESSLIST_ID, PROCESSLIST_USER, PROCESSLIST_HOST from performance_schema.threads where PROCESSLIST_ID="
+ threadId),
false, 0)
: sendCommand(this.commandBuilder.buildComQuery(null, "SHOW PROCESSLIST"), false, 0);

Resultset rs = ((NativeProtocol) this.protocol).readAllResults(-1, false, resultPacket, false, null, new ResultsetFactory(Type.FORWARD_ONLY, null));

ValueFactory<Long> lvf = new LongValueFactory(getPropertySet());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,6 @@ SocketMetadata.0=Using 'host' value of ''{0}'' to determine locality of connecti
SocketMetadata.1=Locally connected - HostAddress({0}).equals(whereIconnectedTo({1})
SocketMetadata.2=Attempted locally connected check failed - ! HostAddress({0}).equals(whereIconnectedTo({1})
SocketMetadata.3=Remote socket address {0} is not an inet socket address
SocketMetadata.4=No port number present in 'host' from SHOW PROCESSLIST ''{0}'', unable to determine whether locally connected

Statement.0=Connection is closed.
Statement.2=Unsupported character encoding ''{0}''
Expand Down
41 changes: 41 additions & 0 deletions src/test/java/testsuite/regression/ConnectionRegressionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -11322,4 +11322,45 @@ public void testBug93007() throws Exception {
conn2.close();

}

/**
* Tests fix for Bug#29329326, PLEASE AVOID SHOW PROCESSLIST IF POSSIBLE.
*
* @throws Exception
*/
public void testBug29329326() throws Exception {
Properties p = new Properties();
p.setProperty(PropertyKey.queryInterceptors.getKeyName(), Bug29329326QueryInterceptor.class.getName());

JdbcConnection c = (JdbcConnection) getConnectionWithProps(p);
Bug29329326QueryInterceptor qi = (Bug29329326QueryInterceptor) c.getQueryInterceptorsInstances().get(0);
assertTrue("SHOW PROCESSLIST was issued during connection establishing", qi.cnt == 0);

((com.mysql.cj.jdbc.ConnectionImpl) c).isServerLocal();

String ps = ((MysqlConnection) c).getSession().getServerSession().getServerVariable("performance_schema");
if (versionMeetsMinimum(5, 6, 0) // performance_schema.threads in MySQL 5.5 does not contain PROCESSLIST_HOST column
&& ps != null && ("1".contentEquals(ps) || "ON".contentEquals(ps))) {
assertTrue("SHOW PROCESSLIST was issued by isServerLocal()", qi.cnt == 0);
} else {
assertTrue("SHOW PROCESSLIST wasn't issued by isServerLocal()", qi.cnt > 0);
}
}

/**
* Counts the number of issued "SHOW PROCESSLIST" statements.
*/
public static class Bug29329326QueryInterceptor extends BaseQueryInterceptor {
int cnt = 0;

@Override
public <M extends Message> M preProcess(M queryPacket) {
String sql = StringUtils.toString(queryPacket.getByteBuffer(), 1, (queryPacket.getPosition() - 1));
if (sql.contains("SHOW PROCESSLIST")) {
this.cnt++;
}
return null;
}
}

}

0 comments on commit 2e350a5

Please sign in to comment.