OSDN Git Service

Fix deadlock between ActivityManager and BackupManager under some race conditions.
authorlwan89x <liangx.wang@intel.com>
Wed, 24 Sep 2014 10:27:49 +0000 (18:27 +0800)
committerChih-Wei Huang <cwhuang@linux.org.tw>
Wed, 20 Jul 2016 09:53:16 +0000 (17:53 +0800)
Deadlock may happen when bind backup agent under some race condition.
If waiting for backup agent timeout, BackupManager will call to
ActivityManager's clearPendingBackup with mAgentConnectLock held.
During clearPendingBackup process, it will try to lock ActivityManager's
main lock. If app started up timeout at the same time, ActivityManager
will call to BackupManager's agentDisconnected with main lock held.
During agentDisconnected process, it will try to lock mAgentConnectLock.
Deadlock happened then.

In bindToAgentSynchronous process, move clearPendingBackup out of lock
area to fix this issue.

Change-Id: Ic1acfe1df8fd83d4acff5ce518d86cea4b2fe18b
Tracked-On: https://jira01.devtools.intel.com/browse/OAM-3350
Orig-Tracked-On: https://jira01.devtools.intel.com/browse/IMINAN-43094
Signed-off-by: lwan89 <liang.wang@intel.com>
Reviewed-on: https://android.intel.com:443/400206
Reviewed-on: https://android.intel.com:443/412995

services/backup/java/com/android/server/backup/BackupManagerService.java

index 30d90af..a607c58 100644 (file)
@@ -2231,10 +2231,10 @@ public class BackupManagerService {
     // fire off a backup agent, blocking until it attaches or times out
     IBackupAgent bindToAgentSynchronous(ApplicationInfo app, int mode) {
         IBackupAgent agent = null;
-        synchronized(mAgentConnectLock) {
-            mConnecting = true;
-            mConnectedAgent = null;
-            try {
+        try {
+            synchronized(mAgentConnectLock) {
+                mConnecting = true;
+                mConnectedAgent = null;
                 if (mActivityManager.bindBackupAgent(app, mode)) {
                     Slog.d(TAG, "awaiting agent for " + app);
 
@@ -2248,7 +2248,6 @@ public class BackupManagerService {
                         } catch (InterruptedException e) {
                             // just bail
                             Slog.w(TAG, "Interrupted: " + e);
-                            mActivityManager.clearPendingBackup();
                             return null;
                         }
                     }
@@ -2256,14 +2255,22 @@ public class BackupManagerService {
                     // if we timed out with no connect, abort and move on
                     if (mConnecting == true) {
                         Slog.w(TAG, "Timeout waiting for agent " + app);
-                        mActivityManager.clearPendingBackup();
                         return null;
                     }
                     if (DEBUG) Slog.i(TAG, "got agent " + mConnectedAgent);
                     agent = mConnectedAgent;
                 }
-            } catch (RemoteException e) {
+            }
+        } catch (RemoteException e) {
                 // can't happen - ActivityManager is local
+        } finally {
+            // failed to bind backup agent, clear pending backup
+            if (agent == null) {
+                try {
+                    mActivityManager.clearPendingBackup();
+                } catch (RemoteException e) {
+                    // can't happen - ActivityManager is local
+                }
             }
         }
         return agent;