From 1bb0a456e10d3de863b9637ae914dd51e06c76c5 Mon Sep 17 00:00:00 2001 From: lwan89x Date: Wed, 24 Sep 2014 18:27:49 +0800 Subject: Fix deadlock between ActivityManager and BackupManager under some race conditions. 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 Signed-off-by: lwan89 Signed-off-by: Zhiquan Liu --- .../android/server/backup/BackupManagerService.java | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'services/backup/java/com/android/server') diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 13db985..b3bb9e6 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -2218,10 +2218,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); @@ -2235,7 +2235,6 @@ public class BackupManagerService { } catch (InterruptedException e) { // just bail Slog.w(TAG, "Interrupted: " + e); - mActivityManager.clearPendingBackup(); return null; } } @@ -2243,14 +2242,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; -- cgit v1.1