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 224962 84c8f07ac553b1a57b2d6877803b62aac4964df2
parent 224961 01483c7e8fe9cceb4918b0f1ee208c4cbde2ead5
child 224963 2e761d32b93fb1f7e7d4b8663f91f6e5d2794598
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp, sledru
bugs1066175
milestone34.0a2
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
@@ -126,16 +126,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;
     private static GeckoEditableListener editableListener;
 
     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;
 
@@ -205,16 +206,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);
             }
         });
     }
 
@@ -482,18 +485,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
     public static void notifyIME(int type) {
         if (editableListener != null) {
             editableListener.notifyIME(type);
         }