Bug 912238 - Ignore exceptions that are thrown after calling System.exit. r=mfinkle
authorKartikaya Gupta <kgupta@mozilla.com>
Thu, 27 Feb 2014 08:49:51 -0500
changeset 171437 3b92bea7b2e78893609424e264f42b25f6d7069d
parent 171436 9da8894c69183ad84d7f65872490c249304e5e4f
child 171438 fb009d10f3e6d0f47cdc5f4e88b1d359765f118c
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersmfinkle
bugs912238
milestone30.0a1
Bug 912238 - Ignore exceptions that are thrown after calling System.exit. r=mfinkle
mobile/android/base/BrowserApp.java
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoAppShell.java
mobile/android/base/GeckoThread.java
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -2396,17 +2396,17 @@ abstract public class BrowserApp extends
                     if (itemId == 0) {
                         String args = "";
                         if (type == GuestModeDialog.ENTERING) {
                             args = GUEST_BROWSING_ARG;
                         } else {
                             GeckoProfile.leaveGuestSession(BrowserApp.this);
                         }
                         doRestart(args);
-                        System.exit(0);
+                        GeckoAppShell.systemExit();
                     }
                 } catch(JSONException ex) {
                     Log.e(LOGTAG, "Exception reading guest mode prompt result", ex);
                 }
             }
         });
 
         Resources res = getResources();
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -447,17 +447,17 @@ public abstract class GeckoApp
     }
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         if (item.getItemId() == R.id.quit) {
             if (GeckoThread.checkAndSetLaunchState(GeckoThread.LaunchState.GeckoRunning, GeckoThread.LaunchState.GeckoExiting)) {
                 GeckoAppShell.notifyGeckoOfEvent(GeckoEvent.createBroadcastEvent("Browser:Quit", null));
             } else {
-                System.exit(0);
+                GeckoAppShell.systemExit();
             }
             return true;
         }
 
         return super.onOptionsItemSelected(item);
     }
 
     @Override
@@ -1230,17 +1230,17 @@ public abstract class GeckoApp
         // Did the OS locale change while we were backgrounded? If so,
         // we need to die so that Gecko will re-init add-ons that touch
         // the UI.
         // This is using a sledgehammer to crack a nut, but it'll do for
         // now.
         if (LocaleManager.systemLocaleDidChange()) {
             Log.i(LOGTAG, "System locale changed. Restarting.");
             doRestart();
-            System.exit(0);
+            GeckoAppShell.systemExit();
             return;
         }
 
         if (GeckoThread.isCreated()) {
             // This happens when the GeckoApp activity is destroyed by Android
             // without killing the entire application (see Bug 769269).
             mIsRestoringActivity = true;
             Telemetry.HistogramAdd("FENNEC_RESTORING_ACTIVITY", 1);
@@ -1881,19 +1881,19 @@ public abstract class GeckoApp
                 alertCookie = "";
         }
         handleNotification(ACTION_ALERT_CALLBACK, alertName, alertCookie);
     }
 
     @Override
     protected void onNewIntent(Intent intent) {
         if (GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoExiting)) {
-            // We're exiting and shouldn't try to do anything else just incase
-            // we're hung for some reason we'll force the process to exit
-            System.exit(0);
+            // We're exiting and shouldn't try to do anything else. In the case
+            // where we are hung while exiting, we should force the process to exit.
+            GeckoAppShell.systemExit();
             return;
         }
 
         // if we were previously OOM killed, we can end up here when launching
         // from external shortcuts, so set this as the intent for initialization
         if (!mInitialized) {
             setIntent(intent);
             return;
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -379,16 +379,22 @@ public class GeckoAppShell
     public static native void notifyGeckoOfEvent(GeckoEvent event);
 
     /*
      *  The Gecko-side API: API methods that Gecko calls
      */
 
     @WrapElementForJNI(allowMultithread = true, generateStatic = true, noThrow = true)
     public static void handleUncaughtException(Thread thread, Throwable e) {
+        if (GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoExited)) {
+            // We've called System.exit. All exceptions after this point are Android
+            // berating us for being nasty to it.
+            return;
+        }
+
         if (thread == null) {
             thread = Thread.currentThread();
         }
         // If the uncaught exception was rethrown, walk the exception `cause` chain to find
         // the original exception so Socorro can correctly collate related crash reports.
         Throwable cause;
         while ((cause = e.getCause()) != null) {
             e = cause;
@@ -694,17 +700,22 @@ public class GeckoAppShell
         if (getGeckoInterface() != null) {
             if (gRestartScheduled) {
                 getGeckoInterface().doRestart();
             } else {
                 getGeckoInterface().getActivity().finish();
             }
         }
 
+        systemExit();
+    }
+
+    static void systemExit() {
         Log.d(LOGTAG, "Killing via System.exit()");
+        GeckoThread.setLaunchState(GeckoThread.LaunchState.GeckoExited);
         System.exit(0);
     }
 
     @WrapElementForJNI
     static void scheduleRestart() {
         gRestartScheduled = true;
     }
 
--- a/mobile/android/base/GeckoThread.java
+++ b/mobile/android/base/GeckoThread.java
@@ -29,17 +29,18 @@ public class GeckoThread extends Thread 
     private static final String LOGTAG = "GeckoThread";
 
     @RobocopTarget
     public enum LaunchState {
         Launching,
         WaitForDebugger,
         Launched,
         GeckoRunning,
-        GeckoExiting
+        GeckoExiting,
+        GeckoExited
     };
 
     private static LaunchState sLaunchState = LaunchState.Launching;
 
     private static GeckoThread sGeckoThread;
 
     private final String mArgs;
     private final String mAction;