Bug #76032 resultset.close() hangs
Submitted: 24 Feb 2015 18:15 Modified: 10 Mar 2015 18:35
Reporter: Quartz 12h Email Updates:
Status: Duplicate Impact on me:
None 
Category:Connector / J Severity:S1 (Critical)
Version:5.1.34 OS:Windows (possibly all OSes)
Assigned to: Filipe Silva CPU Architecture:Any
Tags: close, hangs, hung, KILL, query, ResultSet

[24 Feb 2015 18:15] Quartz 12h
Description:
This is prety much identical to bug #64204 which is marked as closed, but I can still reproduce it.

We found the hung thread in prod, while there isn't any code calling "KILL QUERY #"  but there is code calling "KILL #".

Example stack dump from the test program:

java.sql.SQLException: Query execution was interrupted
	at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2921)
	at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:770)
	at com.mysql.jdbc.MysqlIO.nextRow(MysqlIO.java:1288)
	at com.mysql.jdbc.RowDataDynamic.nextRecord(RowDataDynamic.java:362)
	at com.mysql.jdbc.RowDataDynamic.next(RowDataDynamic.java:352)
	at com.mysql.jdbc.ResultSet.next(ResultSet.java:6071)
	at stress.TableStreamer2.queryIt(TableStreamer2.java:90)
	at stress.TableStreamer2.main(TableStreamer2.java:59)

How to repeat:
a) Create a properties file containing:

Example:

user=foo
password=bar
path=c:/temp/mysql-connector-java-5.1.34-bin.jar
driverclass=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/somedb
sqlquery=SELECT * FROM sometable
useUnbufferedInput=false

b) Use a large table you already populated. Over 100'000 rows if possible, otherwise you should change the Thread.sleep(5) delay to give you the time to kill query.

c) Call "java TableStreamer2 <configfile>"

d) with a mysql console, show processlist to find your query pid, and issue a "KILL QUERY <pid>"

e) observe the program will finish reading some buffered rows, and fail in rs.next() as expected, but will not terminate but hang in the rs.close().
[24 Feb 2015 18:17] Quartz 12h
test program

Attachment: TableStreamer2.java (text/x-java-source), 3.27 KiB.

[24 Feb 2015 18:23] Quartz 12h
The stacktrace above is only the failure upon KILL QUERY on a 3.1.10 driver, so ignore that if you want.

The stackdump where it is hung after failoing the rs.next()
on driver 5.1.34 is:

Thread [main] (Suspended)	
	owns: com.mysql.jdbc.util.ReadAheadInputStream  (id=30)	
	owns: com.mysql.jdbc.JDBC4Connection  (id=31)	
	java.net.SocketInputStream.socketRead0(java.io.FileDescriptor, byte[], int, int, int) line: not available [native method]	
	java.net.SocketInputStream.read(byte[], int, int, int) line: 152	
	java.net.SocketInputStream.read(byte[], int, int) line: 122	
	com.mysql.jdbc.util.ReadAheadInputStream.fill(int) line: 100	
	com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(byte[], int, int) line: 143	
	com.mysql.jdbc.util.ReadAheadInputStream.read(byte[], int, int) line: 173	
	com.mysql.jdbc.MysqlIO.readFully(java.io.InputStream, byte[], int, int) line: 2911	
	com.mysql.jdbc.MysqlIO.reuseAndReadPacket(com.mysql.jdbc.Buffer, int) line: 3337	
	com.mysql.jdbc.MysqlIO.reuseAndReadPacket(com.mysql.jdbc.Buffer) line: 3327	
	com.mysql.jdbc.MysqlIO.checkErrorPacket(int) line: 3814	
	com.mysql.jdbc.MysqlIO.checkErrorPacket() line: 870	
	com.mysql.jdbc.MysqlIO.nextRow(com.mysql.jdbc.Field[], int, boolean, int, boolean, boolean, boolean, com.mysql.jdbc.Buffer) line: 1928	
	com.mysql.jdbc.RowDataDynamic.nextRecord() line: 378	
	com.mysql.jdbc.RowDataDynamic.next() line: 358	
	com.mysql.jdbc.RowDataDynamic.close() line: 158	
	com.mysql.jdbc.JDBC4ResultSet(com.mysql.jdbc.ResultSetImpl).realClose(boolean) line: 6702	
	com.mysql.jdbc.JDBC4ResultSet(com.mysql.jdbc.ResultSetImpl).close() line: 842	
	stress.TableStreamer2.queryIt(java.sql.Connection, int, int, int, int, int, java.lang.String) line: 104	
	stress.TableStreamer2.main(java.lang.String[]) line: 59
[10 Mar 2015 18:35] Filipe Silva
Hi,

Thank you for this bug report. This is a duplicate of Bug#75309 which is already fixed. You should expect this fixed in next Connector/J release.