diff options
| author | 2010-02-24 15:45:06 +0100 | |
|---|---|---|
| committer | 2010-03-01 09:12:07 -0800 | |
| commit | 7bb2581e6f404da0edba9ebb81b0d0593715eb40 (patch) | |
| tree | 1ca3c4dc2d86df5df6a55db38fdd5804eef81cdd | |
| parent | 853226b147fb7be7709ce55e7100ebfea6719435 (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.java | 24 |
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; } } |