Bug #8668 Serious double-add bug in connection pooling code
Submitted: 22 Feb 2005 4:59 Modified: 10 Apr 2007 14:09
Reporter: Bryan Berg Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / NET Severity:S2 (Serious)
Version:1.0.4 OS:Linux (Fedora Core 2 (Mono 1.1.3))
Assigned to: CPU Architecture:Any

[22 Feb 2005 4:59] Bryan Berg
Description:
Closing a connection more than once can cause it to be re-used more than once.  The connections get added to the idlePool more than once in MySqlConnection.Close(); when multiple threads try to write to the same socket, kittens die and very bad things happen.  What we were seeing is that our code was calling Close() more than once and subsequent calls to GetPooledConnection() were returning the same driver instance to multiple threads.

How to repeat:
Calling MySqlConnection.Close multiple times (generally in rapid succession) can cause a connection to be added to the idle pool multiple times.  It's something of a race condition, so hard to reproduce, but we spent several hours trying to track down exactly where the problem was occurring.  What we found was that there was no direct checking to ensure that a connection isn't placed into the idlePool more than once.

Suggested fix:
*** MySqlPool.cs.orig   2004-12-10 14:54:00.000000000 -0800
--- MySqlPool.cs        2005-02-21 19:12:56.000000000 -0800
***************
*** 159,168 ****
                                lock (inUsePool.SyncRoot)
                                {
                                        inUsePool.Remove( driver );
!                                       if (driver.Settings.ConnectionLifetime != 0 && driver.IsTooOld())
                                                driver.Close();
!                                       else
                                                idlePool.Add( driver );
                                }
                }

--- 159,172 ----
                                lock (inUsePool.SyncRoot)
                                {
                                        inUsePool.Remove( driver );
!                                       if (driver.Settings.ConnectionLifetime != 0 && driver.IsTooOld())
!                                       {
                                                driver.Close();
!                                       }
!                                       else if (!idlePool.Contains(driver))
!                                       {
                                                idlePool.Add( driver );
+                                       }
                                }
                }
[3 Mar 2005 21:20] Bryan Berg
We are also able to reproduce this in Windows on Server 2003.  Has anyone even taken a look at this yet?
[11 Oct 2005 7:52] Vasily Kishkin
Could you please provide some test case ?
[12 Nov 2005 0:00] Bugs System
No feedback was provided for this bug for over a month, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
[10 Apr 2007 14:09] Reggie Burnett
This is an old bug but code similar to the suggested fix was added to the most recent GA releases of the products.