From 8f7f836598bedcb3a9f4794a3423656d4969aac3 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Thu, 25 Feb 2021 14:55:13 -0500 Subject: [PATCH] Add logging around the message processing lock. --- .../securesms/crypto/DatabaseSessionLock.java | 29 +++++++++++++++++++ .../messages/IncomingMessageProcessor.java | 7 +++++ 2 files changed, 36 insertions(+) diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/DatabaseSessionLock.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/DatabaseSessionLock.java index baa2b1a311..eb38050d1a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/DatabaseSessionLock.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/DatabaseSessionLock.java @@ -13,6 +13,10 @@ public enum DatabaseSessionLock implements SignalSessionLock { INSTANCE; + public static final long NO_OWNER = -1; + + private volatile long ownerThreadId = NO_OWNER; + @Override public Lock acquire() { SQLiteDatabase db = DatabaseFactory.getInstance(ApplicationDependencies.getApplication()).getRawDatabase(); @@ -23,9 +27,34 @@ public enum DatabaseSessionLock implements SignalSessionLock { db.beginTransaction(); + ownerThreadId = Thread.currentThread().getId(); + return () -> { + ownerThreadId = -1; db.setTransactionSuccessful(); db.endTransaction(); }; } + + /** + * Important: Only truly useful for debugging. Do not rely on this for functionality. There's tiny + * windows where this state might not be fully accurate. + * + * @return True if it's likely that some other thread owns this lock, and it's not you. + */ + public boolean isLikelyHeldByOtherThread() { + long ownerThreadId = this.ownerThreadId; + return ownerThreadId != -1 && ownerThreadId == Thread.currentThread().getId(); + } + + /** + * Important: Only truly useful for debugging. Do not rely on this for functionality. There's a + * tiny window where a thread may still own the lock, but the state we track around it has been + * cleared. + * + * @return The ID of the thread that likely owns this lock, or {@link #NO_OWNER} if no one owns it. + */ + public long getLikeyOwnerThreadId() { + return ownerThreadId; + } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/IncomingMessageProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/messages/IncomingMessageProcessor.java index 3605fb91f2..a25ac0e431 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/IncomingMessageProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/IncomingMessageProcessor.java @@ -113,7 +113,14 @@ public class IncomingMessageProcessor { stopwatch.split("queue-check"); + long ownerThreadId = DatabaseSessionLock.INSTANCE.getLikeyOwnerThreadId(); + if (ownerThreadId != DatabaseSessionLock.NO_OWNER && ownerThreadId != Thread.currentThread().getId()) { + Log.i(TAG, "It is likely that some other thread has this lock. Owner: " + ownerThreadId + ", Us: " + Thread.currentThread().getId()); + } + try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) { + Log.i(TAG, "Acquired lock while processing message " + envelope.getTimestamp() + "."); + DecryptionResult result = MessageDecryptionUtil.decrypt(context, envelope); stopwatch.split("decrypt");