From c3a32b861d6c0f57ad6505db337a33e76d71263f Mon Sep 17 00:00:00 2001 From: Kweku Adams Date: Mon, 13 Jul 2020 15:52:00 -0700 Subject: [PATCH] Avoid overlapping jobstore disk writes. Given that a followup write could be scheduled while one is already going on, if the first one took too long, then the send write could start and overlap with the first write. This change prevents that and makes sure there's only one write happening at a time. Bug: N/A Test: atest CtsJobSchedulerTestCases Test: atest FrameworksServicesTests:JobStoreTest Change-Id: Ie77510508795e5395a24a40266178283d0c525cb --- .../java/com/android/server/job/JobStore.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java index f2a55805d70a7..7bd51b77a119e 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java @@ -335,7 +335,7 @@ public final class JobStore { Slog.v(TAG, "Scheduling persist of jobs to disk."); } mIoHandler.postDelayed(mWriteRunnable, JOB_PERSIST_DELAY); - mWriteScheduled = mWriteInProgress = true; + mWriteScheduled = true; } } } @@ -353,7 +353,7 @@ public final class JobStore { throw new IllegalStateException("An asynchronous write is already scheduled."); } - mWriteScheduled = mWriteInProgress = true; + mWriteScheduled = true; mWriteRunnable.run(); } } @@ -369,7 +369,7 @@ public final class JobStore { final long start = SystemClock.uptimeMillis(); final long end = start + maxWaitMillis; synchronized (mWriteScheduleLock) { - while (mWriteInProgress) { + while (mWriteScheduled || mWriteInProgress) { final long now = SystemClock.uptimeMillis(); if (now >= end) { // still not done and we've hit the end; failure @@ -404,6 +404,12 @@ public final class JobStore { // a bit of lock contention. synchronized (mWriteScheduleLock) { mWriteScheduled = false; + if (mWriteInProgress) { + // Another runnable is currently writing. Postpone this new write task. + maybeWriteStatusToDiskAsync(); + return; + } + mWriteInProgress = true; } synchronized (mLock) { // Clone the jobs so we can release the lock before writing.