Bug 959214 - Use unwinder when getting ANR native stack; r=blassey
authorJim Chen <nchen@mozilla.com>
Wed, 05 Feb 2014 12:37:54 -0600
changeset 167063 2414def6feab69a30883d9845ccee887032cf2f4
parent 167062 a8d39ea091484bbfa8e5ea3b709bfb75e8d348f9
child 167064 c6d28c1dcfeeda7e15f6bc4bc09e06940309ee19
push idunknown
push userunknown
push dateunknown
reviewersblassey
bugs959214
milestone30.0a1
Bug 959214 - Use unwinder when getting ANR native stack; r=blassey
mobile/android/base/ANRReporter.java
mozglue/android/jni-stubs.inc
widget/android/AndroidJNI.cpp
--- a/mobile/android/base/ANRReporter.java
+++ b/mobile/android/base/ANRReporter.java
@@ -49,17 +49,17 @@ public final class ANRReporter extends B
     private static final String TRACES_CHARSET = "utf-8";
     private static final String PING_CHARSET = "utf-8";
 
     private static final ANRReporter sInstance = new ANRReporter();
     private static int sRegisteredCount;
     private Handler mHandler;
     private volatile boolean mPendingANR;
 
-    private static native boolean requestNativeStack();
+    private static native boolean requestNativeStack(boolean unwind);
     private static native String getNativeStack();
     private static native void releaseNativeStack();
 
     public static void register(Context context) {
         if (sRegisteredCount++ != 0) {
             // Already registered
             return;
         }
@@ -455,17 +455,19 @@ public final class ANRReporter extends B
         ping.write(data);
         if (DEBUG) {
             Log.d(LOGTAG, "wrote ping footer, size = " + String.valueOf(data.length + total));
         }
     }
 
     private static void processTraces(Reader traces, File pingFile) {
 
-        boolean haveNativeStack = requestNativeStack();
+        // Unwinding is memory intensive; only unwind if we have enough memory
+        boolean haveNativeStack = requestNativeStack(
+            /* unwind */ SysInfo.getMemSize() >= 640);
         try {
             OutputStream ping = new BufferedOutputStream(
                 new FileOutputStream(pingFile), TRACES_BLOCK_SIZE);
             try {
                 fillPingHeader(ping, pingFile.getName());
                 // Traces file has the format
                 //    ----- pid xxx at xxx -----
                 //    Cmd line: org.mozilla.xxx
--- a/mozglue/android/jni-stubs.inc
+++ b/mozglue/android/jni-stubs.inc
@@ -528,26 +528,26 @@ Java_org_mozilla_gecko_gfx_NativePanZoom
 #endif
 
 #ifdef JNI_BINDINGS
   xul_dlsym("Java_org_mozilla_gecko_gfx_NativePanZoomController_getOverScrollMode", &f_Java_org_mozilla_gecko_gfx_NativePanZoomController_getOverScrollMode);
 #endif
 
 #ifdef JNI_STUBS
 
-typedef jboolean (*Java_org_mozilla_gecko_ANRReporter_requestNativeStack_t)(JNIEnv *, jclass);
+typedef jboolean (*Java_org_mozilla_gecko_ANRReporter_requestNativeStack_t)(JNIEnv *, jclass, jboolean);
 static Java_org_mozilla_gecko_ANRReporter_requestNativeStack_t f_Java_org_mozilla_gecko_ANRReporter_requestNativeStack;
 extern "C" NS_EXPORT jboolean JNICALL
-Java_org_mozilla_gecko_ANRReporter_requestNativeStack(JNIEnv * arg0, jclass arg1) {
+Java_org_mozilla_gecko_ANRReporter_requestNativeStack(JNIEnv * arg0, jclass arg1, jboolean arg2) {
     if (!f_Java_org_mozilla_gecko_ANRReporter_requestNativeStack) {
         arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
                        "JNI Function called before it was loaded");
         return false;
     }
-    return f_Java_org_mozilla_gecko_ANRReporter_requestNativeStack(arg0, arg1);
+    return f_Java_org_mozilla_gecko_ANRReporter_requestNativeStack(arg0, arg1, arg2);
 }
 #endif
 
 #ifdef JNI_BINDINGS
   xul_dlsym("Java_org_mozilla_gecko_ANRReporter_requestNativeStack", &f_Java_org_mozilla_gecko_ANRReporter_requestNativeStack);
 #endif
 
 #ifdef JNI_STUBS
--- a/widget/android/AndroidJNI.cpp
+++ b/widget/android/AndroidJNI.cpp
@@ -940,31 +940,45 @@ Java_org_mozilla_gecko_gfx_NativePanZoom
 NS_EXPORT jint JNICALL
 Java_org_mozilla_gecko_gfx_NativePanZoomController_getOverScrollMode(JNIEnv* env, jobject instance)
 {
     // FIXME implement this
     return 0;
 }
 
 NS_EXPORT jboolean JNICALL
-Java_org_mozilla_gecko_ANRReporter_requestNativeStack(JNIEnv*, jclass)
+Java_org_mozilla_gecko_ANRReporter_requestNativeStack(JNIEnv*, jclass, jboolean aUnwind)
 {
     if (profiler_is_active()) {
         // Don't proceed if profiler is already running
         return JNI_FALSE;
     }
     // WARNING: we are on the ANR reporter thread at this point and it is
     // generally unsafe to use the profiler from off the main thread. However,
     // the risk here is limited because for most users, the profiler is not run
     // elsewhere. See the discussion in Bug 863777, comment 13
-    const char *NATIVE_STACK_FEATURES[] = {"leaf", "threads", "privacy"};
+    const char *NATIVE_STACK_FEATURES[] =
+        {"leaf", "threads", "privacy"};
+    const char *NATIVE_STACK_UNWIND_FEATURES[] =
+        {"leaf", "threads", "privacy", "stackwalk"};
+
+    const char **features = NATIVE_STACK_FEATURES;
+    size_t features_size = sizeof(NATIVE_STACK_FEATURES);
+    if (aUnwind) {
+        features = NATIVE_STACK_UNWIND_FEATURES;
+        features_size = sizeof(NATIVE_STACK_UNWIND_FEATURES);
+        // We want the new unwinder if the unwind mode has not been set yet
+        putenv("MOZ_PROFILER_NEW=1");
+    }
+
+    const char *NATIVE_STACK_THREADS[] =
+        {"GeckoMain", "Compositor"};
     // Buffer one sample and let the profiler wait a long time
-    profiler_start(100, 10000, NATIVE_STACK_FEATURES,
-        sizeof(NATIVE_STACK_FEATURES) / sizeof(char*),
-        nullptr, 0);
+    profiler_start(100, 10000, features, features_size / sizeof(char*),
+        NATIVE_STACK_THREADS, sizeof(NATIVE_STACK_THREADS) / sizeof(char*));
     return JNI_TRUE;
 }
 
 NS_EXPORT jstring JNICALL
 Java_org_mozilla_gecko_ANRReporter_getNativeStack(JNIEnv* jenv, jclass)
 {
     if (!profiler_is_active()) {
         // Maybe profiler support is disabled?