EventPipe: fix memory leaks (#12476)
authorKonstantin Baladurin <k.baladurin@partner.samsung.com>
Mon, 28 Aug 2017 19:02:12 +0000 (22:02 +0300)
committerBrian Robbins <brianrob@microsoft.com>
Mon, 28 Aug 2017 19:02:12 +0000 (12:02 -0700)
src/vm/eventpipebuffermanager.cpp
src/vm/eventpipebuffermanager.h
src/vm/eventpipeconfiguration.cpp
src/vm/eventpipeprovider.cpp

index fa4c5e0..e7d97d5 100644 (file)
@@ -33,6 +33,49 @@ EventPipeBufferManager::EventPipeBufferManager()
 #endif // _DEBUG
 }
 
+EventPipeBufferManager::~EventPipeBufferManager()
+{
+    CONTRACTL
+    {
+        THROWS;
+        GC_TRIGGERS;
+        MODE_ANY;
+    }
+    CONTRACTL_END;
+
+    if(m_pPerThreadBufferList != NULL)
+    {
+        SListElem<EventPipeBufferList*> *pElem = m_pPerThreadBufferList->GetHead();
+        while(pElem != NULL)
+        {
+            SListElem<EventPipeBufferList*> *pCurElem = pElem;
+
+            EventPipeBufferList *pThreadBufferList = pCurElem->GetValue();
+            if (!pThreadBufferList->OwnedByThread())
+            {
+                Thread *pThread = NULL;
+                while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL)
+                {
+                    if (pThread->GetEventPipeBufferList() == pThreadBufferList)
+                    {
+                        pThread->SetEventPipeBufferList(NULL);
+                        break;
+                    }
+                }
+
+                // We don't delete buffers themself because they can be in-use
+                delete(pThreadBufferList);
+            }
+
+            pElem = m_pPerThreadBufferList->GetNext(pElem);
+            delete(pCurElem);
+        }
+
+        delete(m_pPerThreadBufferList);
+        m_pPerThreadBufferList = NULL;
+    }
+}
+
 EventPipeBuffer* EventPipeBufferManager::AllocateBufferForThread(Thread *pThread, unsigned int requestSize)
 {
     CONTRACTL
@@ -436,8 +479,15 @@ void EventPipeBufferManager::DeAllocateBuffers()
 
                             // In DEBUG, make sure that the element was found and removed.
                             _ASSERTE(pElem != NULL);
+
+                            SListElem<EventPipeBufferList*> *pCurElem = pElem;
+                            pElem = m_pPerThreadBufferList->GetNext(pElem);
+                            delete(pCurElem);
+                        }
+                        else
+                        {
+                            pElem = m_pPerThreadBufferList->GetNext(pElem);
                         }
-                        pElem = m_pPerThreadBufferList->GetNext(pElem);
                     }
 
                     // Remove the list reference from the thread.
@@ -483,12 +533,18 @@ void EventPipeBufferManager::DeAllocateBuffers()
             pElem = m_pPerThreadBufferList->FindAndRemove(pElem);
             _ASSERTE(pElem != NULL);
 
+            SListElem<EventPipeBufferList*> *pCurElem = pElem;
+            pElem = m_pPerThreadBufferList->GetNext(pElem);
+            delete(pCurElem);
+
             // Now that all of the list elements have been freed, free the list itself.
             delete(pBufferList);
             pBufferList = NULL;
         }
-
-        pElem = m_pPerThreadBufferList->GetNext(pElem);
+        else
+        {
+            pElem = m_pPerThreadBufferList->GetNext(pElem);
+        }
     } 
 }
 
index 23e4e7f..942d4e2 100644 (file)
@@ -62,6 +62,7 @@ private:
 public:
 
     EventPipeBufferManager();
+    ~EventPipeBufferManager();
 
     // Write an event to the input thread's current event buffer.
     // An optional eventThread can be provided for sample profiler events.
index 0a266e4..ee2c382 100644 (file)
@@ -35,6 +35,12 @@ EventPipeConfiguration::~EventPipeConfiguration()
     }
     CONTRACTL_END;
 
+    if(m_pConfigProvider != NULL)
+    {
+        delete(m_pConfigProvider);
+        m_pConfigProvider = NULL;
+    }
+
     if(m_pEnabledProviderList != NULL)
     {
         delete(m_pEnabledProviderList);
@@ -43,6 +49,15 @@ EventPipeConfiguration::~EventPipeConfiguration()
 
     if(m_pProviderList != NULL)
     {
+        SListElem<EventPipeProvider*> *pElem = m_pProviderList->GetHead();
+        while(pElem != NULL)
+        {
+            // We don't delete provider itself because it can be in-use
+            SListElem<EventPipeProvider*> *pCurElem = pElem;
+            pElem = m_pProviderList->GetNext(pElem);
+            delete(pCurElem);
+        }
+
         delete(m_pProviderList);
         m_pProviderList = NULL;
     }
@@ -139,6 +154,7 @@ bool EventPipeConfiguration::UnregisterProvider(EventPipeProvider &provider)
     {
         if(m_pProviderList->FindAndRemove(pElem) != NULL)
         {
+            delete(pElem);
             return true;
         }
     }
@@ -402,9 +418,14 @@ void EventPipeConfiguration::DeleteDeferredProviders()
         {
             // The act of deleting the provider unregisters it and removes it from the list.
             delete(pProvider);
+            SListElem<EventPipeProvider*> *pCurElem = pElem;
+            pElem = m_pProviderList->GetNext(pElem);
+            delete(pCurElem);
+        }
+        else
+        {
+            pElem = m_pProviderList->GetNext(pElem);
         }
-
-        pElem = m_pProviderList->GetNext(pElem);
     }
 }
 
index 896f9b2..f4ddd19 100644 (file)
@@ -65,7 +65,9 @@ EventPipeProvider::~EventPipeProvider()
             EventPipeEvent *pEvent = pElem->GetValue();
             delete pEvent;
 
+            SListElem<EventPipeEvent*> *pCurElem = pElem;
             pElem = m_pEventList->GetNext(pElem);
+            delete pCurElem;
         }
 
         delete m_pEventList;