diff options
author | Dianne Hackborn <hackbod@google.com> | 2009-10-06 17:18:05 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2009-10-07 11:10:33 -0700 |
commit | 0c3154d3fc54a1b3d8358a2932042cca729327b9 (patch) | |
tree | 55b34effec937b2a0bc7a7504d9df73268dcdc32 /services | |
parent | 4625758d0b909ccfc9f40b707666b1b21e9e8ffd (diff) | |
download | frameworks_base-0c3154d3fc54a1b3d8358a2932042cca729327b9.zip frameworks_base-0c3154d3fc54a1b3d8358a2932042cca729327b9.tar.gz frameworks_base-0c3154d3fc54a1b3d8358a2932042cca729327b9.tar.bz2 |
Fix issue #2163654: deadlock, runtime restart
Don't hold a lock when the activity thread is telling the activity manager
to release a provider.
This requires that the activity manager now keep a reference count on the
providers, because without the lock it is possible for activity thread to
call in to request the provider again before it has finished telling
about the release.
Change-Id: I5f912903891f4edae85e28819d4e6f14b8f2e688
Diffstat (limited to 'services')
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 29 | ||||
-rw-r--r-- | services/java/com/android/server/am/ProcessRecord.java | 3 |
2 files changed, 24 insertions, 8 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 34302b1..c611795 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -7542,8 +7542,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (DEBUG_PROVIDER) Log.v(TAG, "Adding provider requested by " + r.processName + " from process " - + cpr.info.processName); - r.conProviders.add(cpr); + + cpr.info.processName); + Integer cnt = r.conProviders.get(cpr); + if (cnt == null) { + r.conProviders.put(cpr, new Integer(1)); + } else { + r.conProviders.put(cpr, new Integer(cnt.intValue()+1)); + } cpr.clients.add(r); } else { cpr.externals++; @@ -7648,8 +7653,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (DEBUG_PROVIDER) Log.v(TAG, "Adding provider requested by " + r.processName + " from process " - + cpr.info.processName); - r.conProviders.add(cpr); + + cpr.info.processName); + Integer cnt = r.conProviders.get(cpr); + if (cnt == null) { + r.conProviders.put(cpr, new Integer(1)); + } else { + r.conProviders.put(cpr, new Integer(cnt.intValue()+1)); + } cpr.clients.add(r); } else { cpr.externals++; @@ -7726,8 +7736,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen + cpr.info.name + " in process " + r.processName); return; } else { - localCpr.clients.remove(r); - r.conProviders.remove(localCpr); + Integer cnt = r.conProviders.get(localCpr); + if (cnt == null || cnt.intValue() <= 1) { + localCpr.clients.remove(r); + r.conProviders.remove(localCpr); + } else { + r.conProviders.put(localCpr, new Integer(cnt.intValue()-1)); + } } updateOomAdjLocked(); } @@ -9914,7 +9929,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen // Unregister from connected content providers. if (!app.conProviders.isEmpty()) { - Iterator it = app.conProviders.iterator(); + Iterator it = app.conProviders.keySet().iterator(); while (it.hasNext()) { ContentProviderRecord cpr = (ContentProviderRecord)it.next(); cpr.clients.remove(app); diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java index d05b44b..6202257 100644 --- a/services/java/com/android/server/am/ProcessRecord.java +++ b/services/java/com/android/server/am/ProcessRecord.java @@ -94,7 +94,8 @@ class ProcessRecord implements Watchdog.PssRequestor { // class (String) -> ContentProviderRecord final HashMap pubProviders = new HashMap(); // All ContentProviderRecord process is using - final HashSet conProviders = new HashSet(); + final HashMap<ContentProviderRecord, Integer> conProviders + = new HashMap<ContentProviderRecord, Integer>(); boolean persistent; // always keep this application running? boolean crashing; // are we in the process of crashing? |