Merge "If an application calls System.exit() terminate it immediately."
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 333c12c..cdd2ad1 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -52,6 +52,7 @@
 
     private static final native void nativeZygoteInit();
     private static final native void nativeFinishInit();
+    private static final native void nativeSetExitWithoutCleanup(boolean exitWithoutCleanup);
 
     /**
      * Use this to log a message when a thread exits due to an uncaught
@@ -281,6 +282,13 @@
 
     private static void applicationInit(int targetSdkVersion, String[] argv)
             throws ZygoteInit.MethodAndArgsCaller {
+        // If the application calls System.exit(), terminate the process
+        // immediately without running any shutdown hooks.  It is not possible to
+        // shutdown an Android application gracefully.  Among other things, the
+        // Android runtime shutdown hooks close the Binder driver, which can cause
+        // leftover running threads to crash before the process actually exits.
+        nativeSetExitWithoutCleanup(true);
+
         // We want to be fairly aggressive about heap utilization, to avoid
         // holding on to a lot of memory that isn't needed.
         VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index d33dccb..e705c47 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -199,6 +199,12 @@
     gCurRuntime->onZygoteInit();
 }
 
+static void com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup(JNIEnv* env,
+        jobject clazz, jboolean exitWithoutCleanup)
+{
+    gCurRuntime->setExitWithoutCleanup(exitWithoutCleanup);
+}
+
 /*
  * JNI registration.
  */
@@ -207,6 +213,8 @@
         (void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
     { "nativeZygoteInit", "()V",
         (void*) com_android_internal_os_RuntimeInit_nativeZygoteInit },
+    { "nativeSetExitWithoutCleanup", "(Z)V",
+        (void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
 };
 
 int register_com_android_internal_os_RuntimeInit(JNIEnv* env)
@@ -220,7 +228,8 @@
 /*static*/ JavaVM* AndroidRuntime::mJavaVM = NULL;
 
 
-AndroidRuntime::AndroidRuntime()
+AndroidRuntime::AndroidRuntime() :
+        mExitWithoutCleanup(false)
 {
     SkGraphics::Init();
     // this sets our preference for 16bit images during decode
@@ -298,8 +307,7 @@
  */
 static void runtime_exit(int code)
 {
-    gCurRuntime->onExit(code);
-    exit(code);
+    gCurRuntime->exit(code);
 }
 
 /*
@@ -870,10 +878,16 @@
         ALOGW("Warning: VM did not shut down cleanly\n");
 }
 
-void AndroidRuntime::onExit(int code)
+void AndroidRuntime::exit(int code)
 {
-    ALOGV("AndroidRuntime onExit calling exit(%d)", code);
-    exit(code);
+    if (mExitWithoutCleanup) {
+        ALOGI("VM exiting with result code %d, cleanup skipped.", code);
+        ::_exit(code);
+    } else {
+        ALOGI("VM exiting with result code %d.", code);
+        onExit(code);
+        ::exit(code);
+    }
 }
 
 void AndroidRuntime::onVmCreated(JNIEnv* env)
diff --git a/include/android_runtime/AndroidRuntime.h b/include/android_runtime/AndroidRuntime.h
index fd33d59..0b3ce9a 100644
--- a/include/android_runtime/AndroidRuntime.h
+++ b/include/android_runtime/AndroidRuntime.h
@@ -66,6 +66,12 @@
 
     void start(const char *classname, const char* options);
 
+    void exit(int code);
+
+    void setExitWithoutCleanup(bool exitWithoutCleanup) {
+        mExitWithoutCleanup = exitWithoutCleanup;
+    }
+
     static AndroidRuntime* getRuntime();
 
     /**
@@ -86,14 +92,13 @@
      * fork. Override it to initialize threads, etc. Upon return, the
      * correct static main will be invoked.
      */
-    virtual void onZygoteInit() {};
-
+    virtual void onZygoteInit() { }
 
     /**
-     * Called when the Java application exits.  The default
-     * implementation calls exit(code).
+     * Called when the Java application exits to perform additional cleanup actions
+     * before the process is terminated.
      */
-    virtual void onExit(int code);
+    virtual void onExit(int code) { }
 
     /** create a new thread that is visible from Java */
     static android_thread_id_t createJavaThread(const char* name, void (*start)(void *),
@@ -114,6 +119,7 @@
     int startVm(JavaVM** pJavaVM, JNIEnv** pEnv);
 
     Vector<JavaVMOption> mOptions;
+    bool mExitWithoutCleanup;
 
     /* JNI JavaVM pointer */
     static JavaVM* mJavaVM;