From b55e0e45f502bbc5d9f3565b14ed81a5d2cb0de8 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Fri, 12 Apr 2019 14:51:14 -0600 Subject: [PATCH] Avoid deadlock There are multiple methods which synchronize(self) in TSAccountMessage and also multiple ones which can occur within a read-write transaction. --- .../src/Account/TSAccountManager.m | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/SignalServiceKit/src/Account/TSAccountManager.m b/SignalServiceKit/src/Account/TSAccountManager.m index 976de737e..e968ffac3 100644 --- a/SignalServiceKit/src/Account/TSAccountManager.m +++ b/SignalServiceKit/src/Account/TSAccountManager.m @@ -259,21 +259,23 @@ NSString *const TSAccountManager_NeedsAccountAttributesUpdateKey = @"TSAccountMa - (uint32_t)getOrGenerateRegistrationId:(YapDatabaseReadWriteTransaction *)transaction { - @synchronized(self) - { - uint32_t registrationID = [[transaction objectForKey:TSAccountManager_LocalRegistrationIdKey - inCollection:TSAccountManager_UserAccountCollection] unsignedIntValue]; - - if (registrationID == 0) { - registrationID = (uint32_t)arc4random_uniform(16380) + 1; - OWSLogWarn(@"Generated a new registrationID: %u", registrationID); - - [transaction setObject:[NSNumber numberWithUnsignedInteger:registrationID] - forKey:TSAccountManager_LocalRegistrationIdKey - inCollection:TSAccountManager_UserAccountCollection]; - } - return registrationID; + // Unlike other methods in this class, there's no need for a `@synchronized` block + // here, since we're already in a write transaction, and all writes occur on a serial queue. + // + // Since other code in this class which uses @synchronized(self) also needs to open write + // transaction, using @synchronized(self) here, inside of a WriteTransaction risks deadlock. + uint32_t registrationID = [[transaction objectForKey:TSAccountManager_LocalRegistrationIdKey + inCollection:TSAccountManager_UserAccountCollection] unsignedIntValue]; + + if (registrationID == 0) { + registrationID = (uint32_t)arc4random_uniform(16380) + 1; + OWSLogWarn(@"Generated a new registrationID: %u", registrationID); + + [transaction setObject:[NSNumber numberWithUnsignedInteger:registrationID] + forKey:TSAccountManager_LocalRegistrationIdKey + inCollection:TSAccountManager_UserAccountCollection]; } + return registrationID; } - (void)registerForPushNotificationsWithPushToken:(NSString *)pushToken