Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1bb0a456 authored by lwan89x's avatar lwan89x Committed by Steve Kondik
Browse files

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: default avatarlwan89 <liang.wang@intel.com>
Signed-off-by: default avatarZhiquan Liu <zhiquan.liu@intel.com>
parent 3d4374ef
Loading
Loading
Loading
Loading
+14 −7
Original line number Diff line number Diff line
@@ -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;
        try {
            synchronized(mAgentConnectLock) {
                mConnecting = true;
                mConnectedAgent = null;
            try {
                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) {
                // 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;