Prevent possible deadlock with LiveRecipientCache.
Thread A: DirectoryHelper#updateContactsDatabase() acquires database lock Thread B: LiveRecipientCache#getSelf() acquires lock on LiveRecipientCache Thread A: DirectoryHelper#updateContactsDatabase() calls Recipient.externalContact(), which eventually needs LiveRecipientCache lock Thread B: Needs to read the database (e.g. line 120) to get information about itself So A has the DB lock but needs the LiveRecipientCache lock, and B has the LiveRecipientCache lock but needs the DB lock. In general, we need to avoid acquiring any new locks in a transaction, but for now, this specific instance looks like it could be solved by using a unique lock for LiveRecipientCache#getSelf().
This commit is contained in:
parent
5605fde777
commit
5a12eedc2c
1 changed files with 5 additions and 1 deletions
|
@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import androidx.annotation.AnyThread;
|
import androidx.annotation.AnyThread;
|
||||||
|
import androidx.annotation.GuardedBy;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
@ -33,11 +34,14 @@ public final class LiveRecipientCache {
|
||||||
private static final int CACHE_MAX = 1000;
|
private static final int CACHE_MAX = 1000;
|
||||||
private static final int CACHE_WARM_MAX = 500;
|
private static final int CACHE_WARM_MAX = 500;
|
||||||
|
|
||||||
|
private static final Object SELF_LOCK = new Object();
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final RecipientDatabase recipientDatabase;
|
private final RecipientDatabase recipientDatabase;
|
||||||
private final Map<RecipientId, LiveRecipient> recipients;
|
private final Map<RecipientId, LiveRecipient> recipients;
|
||||||
private final LiveRecipient unknown;
|
private final LiveRecipient unknown;
|
||||||
|
|
||||||
|
@GuardedBy("SELF_LOCK")
|
||||||
private RecipientId localRecipientId;
|
private RecipientId localRecipientId;
|
||||||
private boolean warmedUp;
|
private boolean warmedUp;
|
||||||
|
|
||||||
|
@ -111,7 +115,7 @@ public final class LiveRecipientCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull Recipient getSelf() {
|
@NonNull Recipient getSelf() {
|
||||||
synchronized (this) {
|
synchronized (SELF_LOCK) {
|
||||||
if (localRecipientId == null) {
|
if (localRecipientId == null) {
|
||||||
UUID localUuid = TextSecurePreferences.getLocalUuid(context);
|
UUID localUuid = TextSecurePreferences.getLocalUuid(context);
|
||||||
String localE164 = TextSecurePreferences.getLocalNumber(context);
|
String localE164 = TextSecurePreferences.getLocalNumber(context);
|
||||||
|
|
Loading…
Add table
Reference in a new issue