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

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