Bug 763138: Telemetry should indicate whether a debugger is attached. r=bsmedberg,smichaud
authorVladan Djeric <vdjeric@mozilla.com>
Thu, 28 Jun 2012 14:57:52 -0400
changeset 97867 23d9d354236ec99b1111462ef5f98c69d119710a
parent 97866 6fd744aca078097b05e9868cd111234ad1f565b3
child 97868 ff1b571741832d3257941fdfbf460935b84e5202
push id11263
push uservdjeric@mozilla.com
push dateThu, 28 Jun 2012 18:58:02 +0000
treeherdermozilla-inbound@23d9d354236e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg, smichaud
bugs763138
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 763138: Telemetry should indicate whether a debugger is attached. r=bsmedberg,smichaud
toolkit/components/telemetry/TelemetryPing.js
xpcom/base/nsDebugImpl.cpp
xpcom/base/nsIDebug2.idl
--- a/toolkit/components/telemetry/TelemetryPing.js
+++ b/toolkit/components/telemetry/TelemetryPing.js
@@ -60,16 +60,18 @@ const MEM_HISTOGRAMS = {
 
 // Seconds of idle time before pinging.
 // On idle-daily a gather-telemetry notification is fired, during it probes can
 // start asynchronous tasks to gather data.  On the next idle the data is sent.
 const IDLE_TIMEOUT_SECONDS = 5 * 60;
 
 var gLastMemoryPoll = null;
 
+let gWasDebuggerAttached = false;
+
 function getLocale() {
   return Cc["@mozilla.org/chrome/chrome-registry;1"].
          getService(Ci.nsIXULChromeRegistry).
          getSelectedLocale('global');
 }
 
 XPCOMUtils.defineLazyServiceGetter(this, "Telemetry",
                                    "@mozilla.org/base/telemetry;1",
@@ -116,16 +118,22 @@ function getSimpleMeasurements() {
     for (let p in appTimestamps) {
       if (!(p in ret) && appTimestamps[p])
         ret[p] = appTimestamps[p] - si.process;
     }
   }
 
   ret.startupInterrupted = new Number(Services.startup.interrupted);
 
+  // Update debuggerAttached flag
+  let debugService = Cc["@mozilla.org/xpcom/debug;1"].getService(Ci.nsIDebug2);
+  let isDebuggerAttached = debugService.isDebuggerAttached;
+  gWasDebuggerAttached = gWasDebuggerAttached || isDebuggerAttached;
+  ret.debuggerAttached = new Number(gWasDebuggerAttached);
+
   ret.js = Cc["@mozilla.org/js/xpc/XPConnect;1"]
            .getService(Ci.nsIJSEngineTelemetryStats)
            .telemetryValue;
 
   return ret;
 }
 
 /**
@@ -771,16 +779,19 @@ TelemetryPing.prototype = {
         this.detachObservers()
       } else {
         this.attachObservers()
       }
       break;
     case "sessionstore-windows-restored":
       Services.obs.removeObserver(this, "sessionstore-windows-restored");
       this._hasWindowRestoredObserver = false;
+      // Check whether debugger was attached during startup
+      let debugService = Cc["@mozilla.org/xpcom/debug;1"].getService(Ci.nsIDebug2);
+      gWasDebuggerAttached = debugService.isDebuggerAttached;
       // fall through
     case "test-gather-startup":
       this.gatherStartupInformation();
       break;
     case "idle-daily":
       // Enqueue to main-thread, otherwise components may be inited by the
       // idle-daily category and miss the gather-telemetry notification.
       Services.tm.mainThread.dispatch((function() {
--- a/xpcom/base/nsDebugImpl.cpp
+++ b/xpcom/base/nsDebugImpl.cpp
@@ -38,16 +38,23 @@
 #include <signal.h>
 #endif
 
 #if defined(XP_WIN)
 #include <tchar.h>
 #include "nsString.h"
 #endif
 
+#if defined(XP_MACOSX)
+#include <stdbool.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/sysctl.h>
+#endif
+
 #include "mozilla/mozalloc_abort.h"
 
 static void
 Abort(const char *aMsg);
 
 static void
 RealBreak();
 
@@ -131,16 +138,50 @@ nsDebugImpl::GetIsDebugBuild(bool* aResu
 
 NS_IMETHODIMP
 nsDebugImpl::GetAssertionCount(PRInt32* aResult)
 {
   *aResult = gAssertionCount;
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsDebugImpl::GetIsDebuggerAttached(bool* aResult)
+{
+  *aResult = false;
+
+#if defined(XP_WIN)
+  *aResult = ::IsDebuggerPresent();
+#elif defined(XP_MACOSX)
+  // Specify the info we're looking for
+  int mib[4];
+  mib[0] = CTL_KERN;
+  mib[1] = KERN_PROC;
+  mib[2] = KERN_PROC_PID;
+  mib[3] = getpid();
+  size_t mibSize = sizeof(mib) / sizeof(int);
+
+  struct kinfo_proc info;
+  size_t infoSize = sizeof(info);
+  memset(&info, 0, infoSize);
+
+  if (sysctl(mib, mibSize, &info, &infoSize, NULL, 0)) {
+    // if the call fails, default to false
+    *aResult = false;
+    return NS_OK;
+  }
+
+  if (info.kp_proc.p_flag & P_TRACED) {
+    *aResult = true;
+  }
+#endif
+
+  return NS_OK;
+}
+
 /* static */ void
 nsDebugImpl::SetMultiprocessMode(const char *aDesc)
 {
   sIsMultiprocess = true;
   sMultiprocessDescription = aDesc;
 }
 
 /**
--- a/xpcom/base/nsIDebug2.idl
+++ b/xpcom/base/nsIDebug2.idl
@@ -2,23 +2,29 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* interface to expose information about calls to NS_DebugBreak */
 
 #include "nsIDebug.idl"
 
-[scriptable, uuid(9c9307ed-480a-4f2a-8f29-21378c03bcbc)]
+[scriptable, uuid(6cb17fec-cdf7-4f7c-b267-37a0acaa9cf1)]
 interface nsIDebug2 : nsIDebug
 {
     /**
      * Whether XPCOM was compiled with DEBUG defined.  This often
      * correlates to whether other code (e.g., Firefox, XULRunner) was
      * compiled with DEBUG defined.
      */
     readonly attribute boolean isDebugBuild;
 
     /**
      * The number of assertions since process start.
      */
     readonly attribute long assertionCount;
+
+    /**
+     * Whether a debugger is currently attached.
+     * Supports Windows + Mac
+     */
+    readonly attribute bool isDebuggerAttached;
 };