Bug 767488 - Cache the current process handle after reading it for the first time during stack walking; r=dbaron
authorEhsan Akhgari <ehsan@mozilla.com>
Fri, 22 Jun 2012 17:48:31 -0400
changeset 98782 2cbf12886c8914b36127cdec5c93ea4884c7d6b1
parent 98781 d9351d6dd5e376a090b9820d2db4954273d99bfa
child 98783 a7f575fe03e018b830454175a70fa7d38f431f94
push id23085
push userryanvm@gmail.com
push dateTue, 10 Jul 2012 22:39:59 +0000
treeherdermozilla-central@340764f48ed2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs767488
milestone16.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 767488 - Cache the current process handle after reading it for the first time during stack walking; r=dbaron The current process handle never changes, so it doesn't make a lot of sense to read it over and over again. Note that this doesn't close the process handle explicitly but that's fine, since Windows will release all of the open handles when the application is terminated.
xpcom/base/nsStackWalk.cpp
--- a/xpcom/base/nsStackWalk.cpp
+++ b/xpcom/base/nsStackWalk.cpp
@@ -434,48 +434,50 @@ WalkStackThread(void* aData)
  * whose in memory address doesn't match its in-file address.
  */
 
 EXPORT_XPCOM_API(nsresult)
 NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
              void *aClosure, uintptr_t aThread)
 {
     MOZ_ASSERT(gCriticalAddress.mInit);
-    HANDLE myProcess, myThread;
+    static HANDLE myProcess = NULL;
+    HANDLE myThread;
     DWORD walkerReturn;
     struct WalkStackData data;
 
     if (!EnsureImageHlpInitialized())
         return false;
 
     HANDLE targetThread = ::GetCurrentThread();
     data.walkCallingThread = true;
     if (aThread) {
         HANDLE threadToWalk = reinterpret_cast<HANDLE> (aThread);
         // walkCallingThread indicates whether we are walking the caller's stack
         data.walkCallingThread = (threadToWalk == targetThread);
         targetThread = threadToWalk;
     }
 
     // Have to duplicate handle to get a real handle.
-    if (!::DuplicateHandle(::GetCurrentProcess(),
-                           ::GetCurrentProcess(),
-                           ::GetCurrentProcess(),
-                           &myProcess,
-                           PROCESS_ALL_ACCESS, FALSE, 0)) {
-        PrintError("DuplicateHandle (process)");
-        return NS_ERROR_FAILURE;
+    if (!myProcess) {
+        if (!::DuplicateHandle(::GetCurrentProcess(),
+                               ::GetCurrentProcess(),
+                               ::GetCurrentProcess(),
+                               &myProcess,
+                               PROCESS_ALL_ACCESS, FALSE, 0)) {
+            PrintError("DuplicateHandle (process)");
+            return NS_ERROR_FAILURE;
+        }
     }
     if (!::DuplicateHandle(::GetCurrentProcess(),
                            targetThread,
                            ::GetCurrentProcess(),
                            &myThread,
                            THREAD_ALL_ACCESS, FALSE, 0)) {
         PrintError("DuplicateHandle (thread)");
-        ::CloseHandle(myProcess);
         return NS_ERROR_FAILURE;
     }
 
     data.skipFrames = aSkipFrames;
     data.thread = myThread;
     data.process = myProcess;
     void *local_pcs[1024];
     data.pcs = local_pcs;
@@ -509,17 +511,16 @@ NS_StackWalk(NS_WalkStackCallback aCallb
                 PrintError("SignalObjectAndWait (2)");
         }
 
         ::CloseHandle(data.eventStart);
         ::CloseHandle(data.eventEnd);
     }
 
     ::CloseHandle(myThread);
-    ::CloseHandle(myProcess);
 
     for (PRUint32 i = 0; i < data.pc_count; ++i)
         (*aCallback)(data.pcs[i], aClosure);
 
     if (data.pc_size > ArrayLength(local_pcs))
         free(data.pcs);
 
     return NS_OK;