Bug 855662 - SPS breakpad: free breakpad-allocated memory when unwinder thread shuts down. r=bgirard
authorJulian Seward <jseward@acm.org>
Fri, 29 Mar 2013 08:36:50 +0100
changeset 126679 5a7aaa967ad3f809b015034939eab2ca9f4a0129
parent 126678 7a41df293babd744ac87ab626b791c11500ff5cd
child 126680 4a57008543aa8cbb0b6072b0c7c166b57249c3d2
push idunknown
push userunknown
push dateunknown
reviewersbgirard
bugs855662
milestone22.0a1
Bug 855662 - SPS breakpad: free breakpad-allocated memory when unwinder thread shuts down. r=bgirard
tools/profiler/UnwinderThread2.cpp
--- a/tools/profiler/UnwinderThread2.cpp
+++ b/tools/profiler/UnwinderThread2.cpp
@@ -113,16 +113,19 @@ static void* unwind_thr_fn ( void* exit_
 static pthread_t unwind_thr;
 static int       unwind_thr_exit_now = 0; // RACED ON
 
 // Threads must be registered with this file before they can be
 // sampled.  So that we know the max safe stack address for each
 // registered thread.
 static void thread_register_for_profiling ( void* stackTop );
 
+// Frees some memory when the unwinder thread is shut down.
+static void do_breakpad_unwind_Buffer_free_singletons();
+
 // RUNS IN SIGHANDLER CONTEXT
 // Acquire an empty buffer and mark it as FILLING
 static UnwinderThreadBuffer* acquire_empty_buffer();
 
 // RUNS IN SIGHANDLER CONTEXT
 // Put this buffer in the queue of stuff going to the unwinder
 // thread, and mark it as FULL.  Before doing that, fill in stack
 // chunk and register fields if a native unwind is requested.
@@ -152,16 +155,17 @@ void uwt__init()
 
 void uwt__deinit()
 {
   // Shut down the unwinder thread.
   MOZ_ASSERT(unwind_thr_exit_now == 0);
   unwind_thr_exit_now = 1;
   do_MBAR();
   int r = pthread_join(unwind_thr, NULL); MOZ_ALWAYS_TRUE(r==0);
+  do_breakpad_unwind_Buffer_free_singletons();
 }
 
 void uwt__register_thread_for_profiling(void* stackTop)
 {
   thread_register_for_profiling(stackTop);
 }
 
 // RUNS IN SIGHANDLER CONTEXT
@@ -808,16 +812,24 @@ static void* unwind_thr_fn(void* exit_no
        else beat us to it. */
     spinLock_release(&g_spinLock);
     UnwinderThreadBuffer** buffers
       = (UnwinderThreadBuffer**)malloc(N_UNW_THR_BUFFERS
                                         * sizeof(UnwinderThreadBuffer*));
     MOZ_ASSERT(buffers);
     int i;
     for (i = 0; i < N_UNW_THR_BUFFERS; i++) {
+      /* These calloc-ations are never freed, even when the unwinder
+         thread is shut down.  The reason is that sampler threads
+         might still be filling them up even after this thread is shut
+         down.  The buffers themselves are not protected by the
+         spinlock, so we have no way to stop them being accessed
+         whilst we free them.  It doesn't matter much since they will
+         not be reallocated if a new unwinder thread is restarted
+         later. */
       buffers[i] = (UnwinderThreadBuffer*)
                    calloc(sizeof(UnwinderThreadBuffer), 1);
       MOZ_ASSERT(buffers[i]);
       buffers[i]->state = S_EMPTY;
     }
     /* Try to install it */
     spinLock_acquire(&g_spinLock);
     if (g_buffers == NULL) {
@@ -1473,16 +1485,32 @@ class MyCodeModules : public google_brea
 
    The first pair is for the outermost frame, the last for the
    innermost frame.
 */
 
 MyCodeModules* sModules = NULL;
 google_breakpad::LocalDebugInfoSymbolizer* sSymbolizer = NULL;
 
+// Free up the above two singletons when the unwinder thread is shut
+// down.
+static
+void do_breakpad_unwind_Buffer_free_singletons()
+{
+  if (sSymbolizer) {
+    delete sSymbolizer;
+    sSymbolizer = NULL;
+  }
+  if (sModules) {
+    delete sModules;
+    sModules = NULL;
+  }
+}
+
+static
 void do_breakpad_unwind_Buffer(/*OUT*/PCandSP** pairs,
                                /*OUT*/unsigned int* nPairs,
                                UnwinderThreadBuffer* buff,
                                int buffNo /* for debug printing only */)
 {
 # if defined(SPS_ARCH_amd64)
   MDRawContextAMD64* context = new MDRawContextAMD64();
   memset(context, 0, sizeof(*context));