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

Commit 336a649c authored by Christopher Tate's avatar Christopher Tate
Browse files

Prevent concurrent backup operations

We've seen cases (bug 5417779) where the transport kicked off an immediate
backup operation but then was perfectly content to allow the periodic
timer to start *another* pass concurrently while the first was still in
progress.  This wound up with the backup manager getting mightily
confused and leaking wakelock acquisitions, which is Very Bad(tm).

This patch adds a little bookkeeping so that the backup manager is aware
of backups in flight, and refuses to kick off a new one until the ongoing
one has finished.

Change-Id: If12b54f4db3effc8af36d31c58d8f9b415ddc01e
parent 63d8b0c8
Loading
Loading
Loading
Loading
+30 −12
Original line number Diff line number Diff line
@@ -228,6 +228,7 @@ class BackupManagerService extends IBackupManager.Stub {
    // completed.
    final Object mAgentConnectLock = new Object();
    IBackupAgent mConnectedAgent;
    volatile boolean mBackupRunning;
    volatile boolean mConnecting;
    volatile long mLastBackupPass;
    volatile long mNextBackupPass;
@@ -434,6 +435,9 @@ class BackupManagerService extends IBackupManager.Stub {
                IBackupTransport transport = getTransport(mCurrentTransport);
                if (transport == null) {
                    Slog.v(TAG, "Backup requested but no transport available");
                    synchronized (mQueueLock) {
                        mBackupRunning = false;
                    }
                    mWakelock.release();
                    break;
                }
@@ -470,6 +474,9 @@ class BackupManagerService extends IBackupManager.Stub {
                    sendMessage(pbtMessage);
                } else {
                    Slog.v(TAG, "Backup requested but nothing pending");
                    synchronized (mQueueLock) {
                        mBackupRunning = false;
                    }
                    mWakelock.release();
                }
                break;
@@ -804,14 +811,19 @@ class BackupManagerService extends IBackupManager.Stub {
                        // Don't run backups now if we're disabled or not yet
                        // fully set up.
                        if (mEnabled && mProvisioned) {
                            if (!mBackupRunning) {
                                if (DEBUG) Slog.v(TAG, "Running a backup pass");

                                // Acquire the wakelock and pass it to the backup thread.  it will
                                // be released once backup concludes.
                                mBackupRunning = true;
                                mWakelock.acquire();

                                Message msg = mBackupHandler.obtainMessage(MSG_RUN_BACKUP);
                                mBackupHandler.sendMessage(msg);
                            } else {
                                Slog.i(TAG, "Backup time but one already running");
                            }
                        } else {
                            Slog.w(TAG, "Backup pass but e=" + mEnabled + " p=" + mProvisioned);
                        }
@@ -1948,10 +1960,15 @@ class BackupManagerService extends IBackupManager.Stub {
                writeRestoreTokens();
            }

            // Set up the next backup pass
            // Set up the next backup pass - at this point we can set mBackupRunning
            // to false to allow another pass to fire, because we're done with the
            // state machine sequence and the wakelock is refcounted.
            synchronized (mQueueLock) {
                mBackupRunning = false;
                if (mStatus == BackupConstants.TRANSPORT_NOT_INITIALIZED) {
                    backupNow();
                }
            }

            // Only once we're entirely finished do we release the wakelock
            Slog.i(TAG, "Backup pass finished.");
@@ -2400,8 +2417,8 @@ class BackupManagerService extends IBackupManager.Stub {
                    mLatchObject.notifyAll();
                }
                sendEndBackup();
                mWakelock.release();
                if (DEBUG) Slog.d(TAG, "Full backup pass complete.");
                mWakelock.release();
            }
        }

@@ -2908,8 +2925,8 @@ class BackupManagerService extends IBackupManager.Stub {
                    mLatchObject.notifyAll();
                }
                sendEndRestore();
                mWakelock.release();
                Slog.d(TAG, "Full restore pass complete.");
                mWakelock.release();
            }
        }

@@ -5630,7 +5647,8 @@ class BackupManagerService extends IBackupManager.Stub {
                    + " / " + (!mProvisioned ? "not " : "") + "provisioned / "
                    + (this.mPendingInits.size() == 0 ? "not " : "") + "pending init");
            pw.println("Auto-restore is " + (mAutoRestore ? "enabled" : "disabled"));
            pw.println("Last backup pass: " + mLastBackupPass
            if (mBackupRunning) pw.println("Backup currently running");
            pw.println("Last backup pass started: " + mLastBackupPass
                    + " (now = " + System.currentTimeMillis() + ')');
            pw.println("  next scheduled: " + mNextBackupPass);