Bug #11654 isClosed does not report if underlying socket has been closed
Submitted: 30 Jun 2005 8:10 Modified: 30 Jun 2005 14:19
Reporter: Al Sutton Email Updates:
Status: Not a Bug Impact on me:
None 
Category:Connector / J Severity:S4 (Feature request)
Version:3.1.10 OS:Java
Assigned to: CPU Architecture:Any

[30 Jun 2005 8:10] Al Sutton
Description:
Attempting to use the setAutoCommit method can fail with a java.net.SocketException if the underlying socket has been closed due to a timeout. Once this exception has been thrown the isClosed method still returns false indicating that the connection is still open.

If the connection is unusable due to the socket being closed the isClosed method should return true indicating that the connection to the database has been closed and is no longer available.

How to repeat:
This must be performed on a connection where setAutoCommit talks to the database over a socket. From looking at the code there appear to be some instances where setAutoCommit does not talk to the database (See lines 4850 to 4876 in the source of com.mysql.jdbc.Connection).

1) Create a JDBC Connection
2) Wait for the socket to be closed due to a inactivity timeout
3) call setAutoCommit( false )
4) An exception should be thrown indicating the socket has been closed
5) call isClosed() which will return false

Suggested fix:
Add code to check for exceptions during setAutoCommit which indicate the socket is closed and reflect the status of the socket in the isClosed return value.
[30 Jun 2005 14:19] Mark Matthews
Sorry. IsClosed() is not required to return true if the socket is closed. In fact, it is a violation of the JDBC specification to do so. IsClosed() _only_ returns true if something has called .close() on the connection. However, you should notice that if the driver has communicated with the server and _that_ communication has failed, the driver calls .close() on the connection internally and .isClosed() will return true.

We don't check the socket before every communciation with the server because 1) there isn't a way to do it without sending data to the server and 2) If the socket is dead the driver will get an exception when it tries to send the data and it then cleans up the internal state of the connection and calls .close() on it.

From http://java.sun.com/j2se/1.5.0/docs/api/java/sql/Connection.html#isClosed():

"Retrieves whether this Connection object has been closed. A connection is closed if the method close has been called on it or if certain fatal errors have occurred. This method is guaranteed to return true only when it is called after the method Connection.close has been called. 

This method generally cannot be called to determine whether a connection to a database is valid or invalid. A typical client can determine that a connection is invalid by catching any exceptions that might be thrown when an operation is attempted.
"