Bug #33267 Pinging a possibly broken connection may do more harm than good?
Submitted: 16 Dec 2007 12:18 Modified: 29 Jan 2008 22:27
Reporter: Gianluca Colombo Email Updates:
Status: Duplicate Impact on me:
Category:Connector / NET Severity:S3 (Non-critical)
Version:5.1.3 and 5.1.4 OS:Microsoft Windows
Assigned to: CPU Architecture:Any
Tags: connection;broken;ping

[16 Dec 2007 12:18] Gianluca Colombo

In an attempt to add more robustness to an application, before using again a Connection object opened some time before, I hoped I could do the following:

If Not Connection.Ping() Then
... then do some job ...

This will check whether the connection is still alive (e.g. not closed by server after 8 hours inactivity timeout or broken socket) before I use it.

This sequence will actually fail on Connection.Open with a NullReference exception, if the connection is actually broken.

Please note that if Ping is not called, the sequence will perform correctly (e.g. calling just Connection.Close+Open) and correct operation will be restored (but I expect performance to be worse).

How to repeat:
1. open a connection to a server, even on localhost
2. stop MySQL server service and restart it
3. try the 4 code lines above

Suggested fix:
Looking at the client source I tried to figure out why, and I did a quick-and-dirty fix, as I urgently needed it.

After ping has reported failure, Connection.Close will simply do nothing, as the connection state is already closed.
When re-opening the same connection instance, the null reference exception is given by the  following piece of code:

 public override void Configure(MySqlConnection conn)
        stream.MaxPacketSize = (ulong) maxPacketSize;
	stream.Encoding = Encoding;
as 'stream' is null.

To improve the behaviour, I did the following:
1. I touched Connection.cs Ping function:

public bool Ping()
    bool result = driver.Ping();
    if (!result)
        //SetState(ConnectionState.Closed, true);
        Close(); //I call the public close method instead of just setting its state
    return result;

2. This won't work unless a second fix is performed in MySqlPool.cs

I added the try/catch block at the bottom, around poolGate.Release();

public void ReleaseConnection(Driver driver)
	lock (lockObject)
		if (inUsePool.Contains(driver))

				if (driver.IsTooOld())

                // we now either have a connection available or have room to make
                // one so we release one slot in our semaphore

		//added try-catch
                {} //might need something else here??
[29 Jan 2008 22:27] Reggie Burnett
This turns out to be a duplicate of 33909 which has now been fixed in 5.1.5 and 5.2+