From 8eeebc593adeddfb4a7695334188b30d76e9d785 Mon Sep 17 00:00:00 2001 From: Daniel Applebaum Date: Sat, 22 May 2010 17:35:05 +0000 Subject: [PATCH] Handle thread interruptions better and fix some race conditions. --- src/com/fsck/k9/service/SleepService.java | 49 ++++++++++++++++------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/src/com/fsck/k9/service/SleepService.java b/src/com/fsck/k9/service/SleepService.java index 94cecca48..0595bdf57 100644 --- a/src/com/fsck/k9/service/SleepService.java +++ b/src/com/fsck/k9/service/SleepService.java @@ -30,6 +30,7 @@ public class SleepService extends CoreService SleepDatum sleepDatum = new SleepDatum(); CountDownLatch latch = new CountDownLatch(1); sleepDatum.latch = latch; + sleepDatum.reacquireLatch = new CountDownLatch(1); sleepData.put(id, sleepDatum); Intent i = new Intent(); @@ -52,32 +53,48 @@ public class SleepService extends CoreService { if (K9.DEBUG) Log.d(K9.LOG_TAG, "SleepService latch timed out for id = " + id + ", thread " + Thread.currentThread().getName()); - // don't call endSleep here or remove the sleepDatum here, instead of the following block. - // We might not get the wakeLock before - // falling asleep again, so we have to get the wakeLock *first* The alarmed version will - // already be running in a WakeLock due to the nature of AlarmManager - sleepDatum = sleepData.get(id); - if (sleepDatum != null) - { - reacquireWakeLock(sleepDatum); - // OK, we have the wakeLock, now we can remove the sleepDatum - sleepData.remove(id); - } - } } catch (InterruptedException ie) { - Log.e(K9.LOG_TAG, "SleepService Interrupted", ie); + Log.e(K9.LOG_TAG, "SleepService Interrupted while awaiting latch", ie); } + SleepDatum releaseDatum = sleepData.remove(id); + if (releaseDatum == null) + { + try + { + if (K9.DEBUG) + Log.d(K9.LOG_TAG, "SleepService waiting for reacquireLatch for id = " + id + ", thread " + Thread.currentThread().getName()); + if (sleepDatum.reacquireLatch.await(5000, TimeUnit.MILLISECONDS) == false) + { + Log.w(K9.LOG_TAG, "SleepService reacquireLatch timed out for id = " + id + ", thread " + Thread.currentThread().getName()); + } + else if (K9.DEBUG) + Log.d(K9.LOG_TAG, "SleepService reacquireLatch finished for id = " + id + ", thread " + Thread.currentThread().getName()); + } + catch (InterruptedException ie) + { + Log.e(K9.LOG_TAG, "SleepService Interrupted while awaiting reacquireLatch", ie); + } + } + else + { + reacquireWakeLock(releaseDatum); + } + long endTime = System.currentTimeMillis(); long actualSleep = endTime - startTime; - if (K9.DEBUG) - Log.d(K9.LOG_TAG, "SleepService requested sleep time was " + sleepTime + ", actual was " + actualSleep); + if (actualSleep < sleepTime) { Log.w(K9.LOG_TAG, "SleepService sleep time too short: requested was " + sleepTime + ", actual was " + actualSleep); } + else + { + if (K9.DEBUG) + Log.d(K9.LOG_TAG, "SleepService requested sleep time was " + sleepTime + ", actual was " + actualSleep); + } } private static void endSleep(Integer id) @@ -99,6 +116,7 @@ public class SleepService extends CoreService latch.countDown(); } reacquireWakeLock(sleepDatum); + sleepDatum.reacquireLatch.countDown(); } else { @@ -139,6 +157,7 @@ public class SleepService extends CoreService CountDownLatch latch; TracingWakeLock wakeLock; long timeout; + CountDownLatch reacquireLatch; } }