Bug 1066175 - Use other means to handle uncaught exception when Gecko is unavailable. r=snorp, a=sledru
authorJim Chen <nchen@mozilla.com>
Wed, 17 Sep 2014 12:59:20 -0400
changeset 216802 e1d77019dda9
parent 216801 4bfa8b78669c
child 216803 0cc0faf4524b
push id3919
push userryanvm@gmail.com
push date2014-09-19 19:44 +0000
treeherdermozilla-beta@0cc0faf4524b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp, sledru
bugs1066175
milestone33.0
Bug 1066175 - Use other means to handle uncaught exception when Gecko is unavailable. r=snorp, a=sledru When the Gecko crash reporter is unavailable, uncaught Java exceptions can end up being ignored. We should try more ways to handle the exception.
mobile/android/base/GeckoAppShell.java
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -116,16 +116,17 @@ import android.widget.Toast;
 public class GeckoAppShell
 {
     private static final String LOGTAG = "GeckoAppShell";
     private static final boolean LOGGING = false;
 
     // We have static members only.
     private GeckoAppShell() { }
 
+    private static Thread.UncaughtExceptionHandler systemUncaughtHandler;
     private static boolean restartScheduled = false;
     private static GeckoEditableListener editableListener = null;
 
     private static final Queue<GeckoEvent> PENDING_EVENTS = new ConcurrentLinkedQueue<GeckoEvent>();
     private static final Map<String, String> ALERT_COOKIES = new ConcurrentHashMap<String, String>();
 
     private static volatile boolean locationHighAccuracyEnabled;
 
@@ -198,16 +199,18 @@ public class GeckoAppShell
     public static void removeObserver(String observerKey) {
         sendEventToGecko(GeckoEvent.createRemoveObserverEvent(observerKey));
     }
     public static native Message getNextMessageFromQueue(MessageQueue queue);
     public static native void onSurfaceTextureFrameAvailable(Object surfaceTexture, int id);
     public static native void dispatchMemoryPressure();
 
     public static void registerGlobalExceptionHandler() {
+        systemUncaughtHandler = Thread.getDefaultUncaughtExceptionHandler();
+
         Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
             @Override
             public void uncaughtException(Thread thread, Throwable e) {
                 handleUncaughtException(thread, e);
             }
         });
     }
 
@@ -445,18 +448,29 @@ public class GeckoAppShell
             }
 
             if (e instanceof OutOfMemoryError) {
                 SharedPreferences prefs = getSharedPreferences();
                 SharedPreferences.Editor editor = prefs.edit();
                 editor.putBoolean(GeckoApp.PREFS_OOM_EXCEPTION, true);
                 editor.commit();
             }
+        } catch (final Throwable exc) {
+            // Report the Java crash below, even if we encounter an exception here.
+        }
+
+        try {
+            reportJavaCrash(getStackTraceString(e));
         } finally {
-            reportJavaCrash(getStackTraceString(e));
+            // reportJavaCrash should have caused us to hard crash. If we're still here,
+            // it probably means Gecko is not loaded, and we should do something else.
+            // Bring up the app crashed dialog so we don't crash silently.
+            if (systemUncaughtHandler != null) {
+                systemUncaughtHandler.uncaughtException(thread, e);
+            }
         }
     }
 
     @WrapElementForJNI(generateStatic = true)
     public static void notifyIME(int type) {
         if (editableListener != null) {
             editableListener.notifyIME(type);
         }