Bug #34338 Memory leak resulting from procedure cache
Submitted: 6 Feb 2008 2:45 Modified: 1 Mar 2008 11:59
Reporter: Maxim Mass
Status: Closed
Category:Connector/Net Severity:S2 (Serious)
Version: OS:Any
Assigned to: Target Version:

[6 Feb 2008 2: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 2: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 21: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 21:24] Reggie Burnett
Verified by visual inspection
[14 Feb 2008 21:24] Reggie Burnett
Fixed in 5.1.6 and 5.2.1
[14 Feb 2008 21: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 11: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.