Bug #696 MySQL timeout connection produce "StackOverflowError" in Java VM
Submitted: 22 Jun 2003 2:28 Modified: 25 Aug 2004 1:20
Reporter: Wilson Chan Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / J Severity:S1 (Critical)
Version:4.0.12 OS:Linux (Linux)
Assigned to: Mark Matthews CPU Architecture:Any

[22 Jun 2003 2:28] Wilson Chan
Description:
According to the VARIABLE "wait_timeout" (default: 28800 seconds) in the manual, 
a running MySQL daemon clears up idle connections if 
their "idle period" > "wait_timeout". 
This works fine on my daemon. But however, after such clear-up happens, 
when I checked my connection objects inside my java ConnectionPool, 
they all returned as "NOT CLOSED". It is demonstrated as follows:

CODE:
=====

// When idle time > wait_timeout

....
Connection conn = connPool.getConnection();
System.out.println("Is conn closed: "+conn.isClosed());
....

Output:
=======

Is conn closed: false

============= End of output ============

Furthermore, when I create a statement with the above Connection object, 
followed by executing a simple query, 
sometimes a "StackOverflowError" is thrown instead of an expected SQLException, 
demonstrated as follows:

CODE:
=====

....
try {

  System.out.println("checkpoint 1");
  Statement s = conn.createStatement();
  System.out.println("checkpoint 2");
  ResultSet r = s.executeQuery("show tables");
  System.out.println("checkpoint 3");

} catch(SQLException e) {
  System.out.println("SQLException catched!!! \n");
  e.printStackTrace();  
} catch(Exception e) {
  System.out.println("Exception catched!!! \n");
  e.printStackTrace();  
} catch (Throwable t) {
  System.out.println("Throwable catched!!! \n");
  t.printStackTrace();
}
....

Expected output:
================
checkpoint 1
checkpoint 2
SQLException catched!!!

SQLException ConnectionPool_PassedValidationTest Sun Jun 22 19:01:55 EST 2003
java.sql.SQLException: Communication link failure: java.io.IOException
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:1604)
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:886)
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:945)
        at com.mysql.jdbc.MysqlIO.sqlQuery(MysqlIO.java:917)
        at com.mysql.jdbc.Connection.execSQL(Connection.java:1841)
        at com.mysql.jdbc.Connection.execSQL(Connection.java:1775)
        at com.mysql.jdbc.Statement.executeQuery(Statement.java:1220)
	
	.............. other unrelated classes (provided on request) .............

UN-Expected output:
===================
checkpoint 1
checkpoint 2
Throwable catched!!!

java.lang.StackOverflowError
        at java.net.SocketOutputStream.socketWrite0(Native Method)
        at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
        at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
        at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:69)
        at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:127)
        at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:1478)
        at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:1405)
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:879)
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:945)
        at com.mysql.jdbc.MysqlIO.sqlQuery(MysqlIO.java:917)
        at com.mysql.jdbc.Connection.execSQL(Connection.java:1841)
        at com.mysql.jdbc.Connection.execSQL(Connection.java:1787)
        at com.mysql.jdbc.Connection.execSQL(Connection.java:1768)
<<< A >>>
        at com.mysql.jdbc.Connection.rollbackNoChecks(Connection.java:1369)
        at com.mysql.jdbc.Connection.rollback(Connection.java:1356)
        at com.mysql.jdbc.Connection.close(Connection.java:1028)
        at com.mysql.jdbc.Connection.cleanup(Connection.java:2050)
        at com.mysql.jdbc.Connection.execSQL(Connection.java:1853)
        at com.mysql.jdbc.Connection.execSQL(Connection.java:1787)
        at com.mysql.jdbc.Connection.execSQL(Connection.java:1768)
<<< B >>>       

	.............. repeat <<< A >>> to <<< B >>> many times ..................	
	
        at com.mysql.jdbc.Connection.rollbackNoChecks(Connection.java:1369)
        at com.mysql.jdbc.Connection.rollback(Connection.java:1356)	
	at com.mysql.jdbc.Connection.close(Connection.java:1028)

============= End of output ============

I wonder if this is either a bug of the Connector/J or a bug of the MySQL daemon. 
Shouldn't conn.isClosed() returns "true" if the connection has been forced 
to shutdown by the MySQL daemon according to wait_timeout? 
And even if it doesn't, why would something other than a java Exception be thrown?

Please have a look at this problem.

I use:
- Connector/J 3.0.7 driver, 
- J2SE 1.4.1_03, 
- Red Hat Linux 8.0 w/kernal 2.4.18 and 
- MySQL 4.0.12

Wilson Chan

How to repeat:
Step 1:
- Set the GLOBAL and SESSION wait_timeout in MySQL to 10 seconds.

Step 2:
- Run the following program by typing "java MySQLStackErrorTest"
- There is a possibility that the StackOverflowError won't appear

==== START OF PROGRAM ====

import java.sql.*;

public class MySQLStackErrorTest {

  /**
    *  Please alter this idle period accordingly.
    *  It only works when it is
    *  > wait_timeout
    *  in MySQL.
    */
  public static final int IDLE_PERIOD = 15 * 1000;

  public static void main(String args[]) throws Throwable {

    /**
      *  Please try a different driver name if this doesn't work for you
      */
    Class.forName("org.gjt.mm.mysql.Driver");

    Connection conn = getConnection();

    do {
        try {

	      System.out.println("Connection closed? "+conn.isClosed());
          Statement s = conn.createStatement();
	      System.out.println("StatementCreated");
	      ResultSet r = s.executeQuery("Show tables");
	      System.out.println("Query OK");
	      Thread.sleep(IDLE_PERIOD);

	    } catch (SQLException e) {
          System.out.println();
		  e.printStackTrace();
		  System.out.println();
		  Thread.sleep(3000);

		}
    } while (true);
  }

  public static Connection getConnection() throws SQLException {
    /**
      *  Please alter the URL, USERNAME and PASSWORD accordingly
      */
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mysql",
                                                  "root",
                                                  "root");
                                                  return conn;
  }
}

==== END OF PROGRAM ====
[22 Jun 2003 5:56] Mark Matthews
This has been fixed in Connector/J 3.0.8 which was released a few weeks ago. Please upgrade to Connector/J 3.0.8 and make sure this solves your problem.
[25 Aug 2004 1:09] Steve McGregory
Experiencing same sort of problem with Connector/J 3.0.12 against MySQL 4.0.17
[25 Aug 2004 1:20] Mark Matthews
Steve,

This is a repeat of BUG#656, which is already fixed in 3.0.14. Please upgrade and test again (as we asked in BUG#656). As a general rule, please make sure you're always running the latest released version of a MySQL product before filing a bug report.

Thanks!