summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Magnus Edlund <magnus.edlund.x@sonyericsson.com> 2010-02-24 15:45:06 +0100
committer Jean-Baptiste Queru <jbq@google.com> 2010-03-01 09:12:07 -0800
commit7bb2581e6f404da0edba9ebb81b0d0593715eb40 (patch)
tree1ca3c4dc2d86df5df6a55db38fdd5804eef81cdd
parent853226b147fb7be7709ce55e7100ebfea6719435 (diff)
Fix problem with restarting an application process that recently has died.
There exists a race condition when starting a process that recently has died. If the ActivityManager receives the death notification for the died process after the new process has been started but before an application thread has been attached to the new process will the newly created process be removed during the cleanup of the died process. If this happens when sending a broadcast could it result in an ANR. This is solved by doing the clean up before starting a new process that uses the same process record.
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java24
1 files changed, 19 insertions, 5 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 1a22a26a5317..5f6356d97edb 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1905,11 +1905,16 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
+ " app=" + app + " knownToBeDead=" + knownToBeDead
+ " thread=" + (app != null ? app.thread : null)
+ " pid=" + (app != null ? app.pid : -1));
- if (app != null &&
- (!knownToBeDead || app.thread == null) && app.pid > 0) {
- return app;
+ if (app != null && app.pid > 0) {
+ if (!knownToBeDead || app.thread == null) {
+ return app;
+ } else {
+ // An application record is attached to a previous process,
+ // clean it up now.
+ handleAppDiedLocked(app, true);
+ }
}
-
+
String hostingNameStr = hostingName != null
? hostingName.flattenToShortString() : null;
@@ -4553,7 +4558,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
mProcDeaths[0]++;
- if (app.thread != null && app.thread.asBinder() == thread.asBinder()) {
+ // Clean up already done if the process has been re-started.
+ if (app.pid == pid && app.thread != null &&
+ app.thread.asBinder() == thread.asBinder()) {
Log.i(TAG, "Process " + app.processName + " (pid " + pid
+ ") has died.");
EventLog.writeEvent(LOG_AM_PROCESS_DIED, app.pid, app.processName);
@@ -4603,6 +4610,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
scheduleAppGcsLocked();
}
}
+ } else if (app.pid != pid) {
+ // A new process has already been started.
+ Log.i(TAG, "Process " + app.processName + " (pid " + pid
+ + ") has died and restarted (pid " + app.pid + ").");
+ EventLog.writeEvent(LOG_AM_PROCESS_DIED, pid, app.processName);
} else if (Config.LOGD) {
Log.d(TAG, "Received spurious death notification for thread "
+ thread.asBinder());
@@ -5424,6 +5436,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
br.resultExtras, br.resultAbort, true);
scheduleBroadcastsLocked();
+ // We need to reset the state if we fails to start the receiver.
+ br.state = BroadcastRecord.IDLE;
}
}