Address deadlocks in profile manager.

// FREEBIE
pull/1/head
Matthew Chen 8 years ago
parent 1fe905f0f9
commit 16d4256e99

@ -307,10 +307,7 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
_localUserProfile.profileKey = [OWSAES256Key generateRandomKey];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(self)
{
[self saveUserProfile:_localUserProfile];
}
[self saveUserProfile:_localUserProfile];
});
}
}
@ -534,21 +531,23 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
// TODO: Revisit this so that failed profile updates don't leave
// the profile avatar blank, etc.
void (^clearLocalAvatar)() = ^{
@synchronized(self)
{
UserProfile *userProfile = self.localUserProfile;
OWSAssert(userProfile);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(self)
{
UserProfile *userProfile = self.localUserProfile;
OWSAssert(userProfile);
// TODO remote avatarUrlPath changes as result of fetching form -
// we should probably invalidate it at that point, and refresh again when
// uploading file completes.
userProfile.avatarUrlPath = nil;
userProfile.avatarFileName = nil;
// TODO remote avatarUrlPath changes as result of fetching form -
// we should probably invalidate it at that point, and refresh again when
// uploading file completes.
userProfile.avatarUrlPath = nil;
userProfile.avatarFileName = nil;
[self saveUserProfile:userProfile];
[self saveUserProfile:userProfile];
self.localCachedAvatarImage = nil;
}
self.localCachedAvatarImage = nil;
}
});
};
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@ -754,17 +753,19 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
- (void)regenerateLocalProfile
{
@synchronized(self)
{
_localUserProfile = nil;
DDLogWarn(@"%@ Removing local user profile", self.tag);
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[transaction removeObjectForKey:kLocalProfileUniqueId inCollection:[UserProfile collection]];
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(self)
{
_localUserProfile = nil;
DDLogWarn(@"%@ Removing local user profile", self.tag);
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[transaction removeObjectForKey:kLocalProfileUniqueId inCollection:[UserProfile collection]];
}];
// rebuild localUserProfile
OWSAssert(self.localUserProfile);
}
// rebuild localUserProfile
OWSAssert(self.localUserProfile);
}
});
}
- (void)addUserToProfileWhitelist:(NSString *)recipientId

@ -10,7 +10,6 @@
#import "NewContactThreadViewController.h"
#import "OWSContactsManager.h"
#import "OWSNavigationController.h"
#import "OWSProfileManager.h"
#import "ProfileViewController.h"
#import "PushManager.h"
#import "Signal-Swift.h"

@ -149,6 +149,19 @@ NS_ASSUME_NONNULL_BEGIN
NSString *localNumber = [TSAccountManager localNumber];
OWSAssert(localNumber.length > 0);
// Many OWSProfileManager methods aren't safe to call from inside a database
// transaction, so do this work now.
OWSProfileManager *profileManager = OWSProfileManager.sharedManager;
BOOL hasLocalProfile = [profileManager hasLocalProfile];
BOOL isThreadInProfileWhitelist = [profileManager isThreadInProfileWhitelist:thread];
BOOL hasUnwhitelistedMember = NO;
for (NSString *recipientId in thread.recipientIdentifiers) {
if (![profileManager isUserInProfileWhitelist:recipientId]) {
hasUnwhitelistedMember = YES;
break;
}
}
ThreadDynamicInteractions *result = [ThreadDynamicInteractions new];
[dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
@ -407,24 +420,14 @@ NS_ASSUME_NONNULL_BEGIN
shouldHaveBlockOffer = NO;
}
if (![OWSProfileManager.sharedManager hasLocalProfile] ||
[OWSProfileManager.sharedManager isThreadInProfileWhitelist:thread]) {
if (!hasLocalProfile || isThreadInProfileWhitelist) {
// Don't show offer if thread is local user hasn't configured their profile.
// Don't show offer if thread is already in profile whitelist.
shouldHaveAddToProfileWhitelistOffer = NO;
} else if (thread.isGroupThread) {
BOOL hasUnwhitelistedMember = NO;
for (NSString *recipientId in thread.recipientIdentifiers) {
if (![OWSProfileManager.sharedManager isUserInProfileWhitelist:recipientId]) {
hasUnwhitelistedMember = YES;
break;
}
}
if (!hasUnwhitelistedMember) {
// Don't show offer in group thread if all members are already individually
// whitelisted.
shouldHaveAddToProfileWhitelistOffer = NO;
}
} else if (thread.isGroupThread && !hasUnwhitelistedMember) {
// Don't show offer in group thread if all members are already individually
// whitelisted.
shouldHaveAddToProfileWhitelistOffer = NO;
}
BOOL shouldHaveContactOffers

@ -6,7 +6,6 @@
#import "NSDate+OWS.h"
#import "OWSOutgoingSyncMessage.h"
#import "OWSSignalServiceProtos.pb.h"
#import "ProfileManagerProtocol.h"
#import "ProtoBuf+OWS.h"
#import "SignalRecipient.h"
#import "TSAttachmentStream.h"

@ -36,10 +36,7 @@ NS_ASSUME_NONNULL_BEGIN
// Once we've shared our profile key with a user (perhaps due to being
// a member of a whitelisted group), make sure they're whitelisted.
id<ProfileManagerProtocol> profileManager = [TextSecureKitEnv sharedEnv].profileManager;
// FIXME PERF avoid this dispatch. It's going to happen for *each* recipient in a group message.
dispatch_async(dispatch_get_main_queue(), ^{
[profileManager addUserToProfileWhitelist:recipientId];
});
[profileManager addUserToProfileWhitelist:recipientId];
}
return [builder build];

Loading…
Cancel
Save