Bug #34338 Memory leak resulting from procedure cache
Submitted: 6 Feb 2008 1:45 Modified: 1 Mar 2008 10:59
Reporter: Maxim Mass Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / NET Severity:S2 (Serious)
Version: OS:Any
Assigned to: CPU Architecture:Any

[6 Feb 2008 1:45] Maxim Mass
Description:
Adding stored procedure metadata into the ProcedureCache can overfill the maximum number of procedures to cache due to a race condition. Once this the list keeps growing with every unique procedure call and never gets trimmed.

How to repeat:
Create a catalog with a few thousand stored procedures and call them repeatedly with multiple threads. Eventually the race condition occurs and every call will keep getting inserted. Since the metadata is stored in DataTables the memory fills up quickly.

Suggested fix:
Changing: if(procHash.Keys.Count == maxSize)
to: if(procHash.Keys.Count >= maxSize)
would address the issue but locking around this shared hash is probably the more correct way to handle it.

Index: C:/MindTouch/redist/MySql Connector 5.14-MT/Source/ProcedureCache.cs
===================================================================
--- C:/MindTouch/redist/MySql Connector 5.14-MT/Source/ProcedureCache.cs	(revision 7202)
+++ C:/MindTouch/redist/MySql Connector 5.14-MT/Source/ProcedureCache.cs	(working copy)
@@ -52,7 +52,11 @@
         {
             int hash = spName.GetHashCode();
 
-            DataSet ds = (DataSet) procHash[hash];
+            DataSet ds = null;
+            lock (procHash.SyncRoot) {
+                ds = (DataSet) procHash[hash];
+            }
+
             if (ds == null)
             {
                 ds = AddNew(conn, spName);
@@ -80,11 +84,12 @@
             DataSet procData = GetProcData(connection, spName);
             if (maxSize > 0)
             {
-                if (procHash.Keys.Count == maxSize)
-                    TrimHash();
                 int hash = spName.GetHashCode();
                 lock (procHash.SyncRoot)
                 {
+                    if (procHash.Keys.Count >= maxSize)
+                        TrimHash();
+
                     if (!procHash.ContainsKey(hash))
                     {
                         procHash[hash] = procData;
[6 Feb 2008 1:48] Maxim Mass
this is what happens after the cache fills up and the race condition occures

Attachment: mysql.data.dll memory use.GIF (image/gif, text), 40.45 KiB.

[14 Feb 2008 20:23] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/42308
[14 Feb 2008 20:24] Reggie Burnett
Verified by visual inspection
[14 Feb 2008 20:24] Reggie Burnett
Fixed in 5.1.6 and 5.2.1
[14 Feb 2008 20:26] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/42309
[1 Mar 2008 10:59] MC Brown
A note has been added to the 5.1.6 and 5.2.1 changelogs: 

A race condition could occur within the procedure cache resulting the cache contents overflowing beyond the configured cache size.