Description:
Hi,
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
Connection.Close
Connection.Open
EndIf
... 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:
NativeDriver.cs:
public override void Configure(MySqlConnection conn)
{
base.Configure(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))
inUsePool.Remove(driver);
if (driver.IsTooOld())
{
driver.Close();
Debug.Assert(!idlePool.Contains(driver));
}
else
idlePool.Enqueue(driver);
// we now either have a connection available or have room to make
// one so we release one slot in our semaphore
//added try-catch
try
{
poolGate.Release();
}
catch
{} //might need something else here??
}
}
}
Description: Hi, 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 Connection.Close Connection.Open EndIf ... 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: NativeDriver.cs: public override void Configure(MySqlConnection conn) { base.Configure(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)) inUsePool.Remove(driver); if (driver.IsTooOld()) { driver.Close(); Debug.Assert(!idlePool.Contains(driver)); } else idlePool.Enqueue(driver); // we now either have a connection available or have room to make // one so we release one slot in our semaphore //added try-catch try { poolGate.Release(); } catch {} //might need something else here?? } } }