Fix concurrency issues accessing TemporaryHost fields that could be changed by other threads

This commit is contained in:
Cameron Gutman
2019-11-06 21:51:23 -08:00
parent 5a0e4bcc05
commit 52dcdd68c4
2 changed files with 21 additions and 18 deletions
+14 -14
View File
@@ -11,24 +11,24 @@
@interface TemporaryHost : NSObject @interface TemporaryHost : NSObject
@property (nonatomic) State state; @property (atomic) State state;
@property (nonatomic) PairState pairState; @property (atomic) PairState pairState;
@property (nonatomic, nullable) NSString * activeAddress; @property (atomic, nullable, retain) NSString * activeAddress;
@property (nonatomic, nullable) NSString * currentGame; @property (atomic, nullable, retain) NSString * currentGame;
@property (nonatomic, nullable, retain) NSData *serverCert; @property (atomic, nullable, retain) NSData *serverCert;
@property (nonatomic, nullable, retain) NSString *address; @property (atomic, nullable, retain) NSString *address;
@property (nonatomic, nullable, retain) NSString *externalAddress; @property (atomic, nullable, retain) NSString *externalAddress;
@property (nonatomic, nullable, retain) NSString *localAddress; @property (atomic, nullable, retain) NSString *localAddress;
@property (nonatomic, nullable, retain) NSString *ipv6Address; @property (atomic, nullable, retain) NSString *ipv6Address;
@property (nonatomic, nullable, retain) NSString *mac; @property (atomic, nullable, retain) NSString *mac;
@property (nonatomic) int serverCodecModeSupport; @property (atomic) int serverCodecModeSupport;
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, retain) NSString *name; @property (atomic, retain) NSString *name;
@property (nonatomic, retain) NSString *uuid; @property (atomic, retain) NSString *uuid;
@property (nonatomic, retain) NSMutableSet *appList; @property (atomic, retain) NSSet *appList;
- (id) initFromHost:(Host*)host; - (id) initFromHost:(Host*)host;
@@ -192,10 +192,11 @@ static NSMutableSet* hostList;
- (void) updateApplist:(NSSet*) newList forHost:(TemporaryHost*)host { - (void) updateApplist:(NSSet*) newList forHost:(TemporaryHost*)host {
DataManager* database = [[DataManager alloc] init]; DataManager* database = [[DataManager alloc] init];
NSMutableSet* newHostAppList = [NSMutableSet setWithSet:host.appList];
for (TemporaryApp* app in newList) { for (TemporaryApp* app in newList) {
BOOL appAlreadyInList = NO; BOOL appAlreadyInList = NO;
for (TemporaryApp* savedApp in host.appList) { for (TemporaryApp* savedApp in newHostAppList) {
if ([app.id isEqualToString:savedApp.id]) { if ([app.id isEqualToString:savedApp.id]) {
savedApp.name = app.name; savedApp.name = app.name;
savedApp.hdrSupported = app.hdrSupported; savedApp.hdrSupported = app.hdrSupported;
@@ -205,7 +206,7 @@ static NSMutableSet* hostList;
} }
if (!appAlreadyInList) { if (!appAlreadyInList) {
app.host = host; app.host = host;
[host.appList addObject:app]; [newHostAppList addObject:app];
} }
} }
@@ -213,7 +214,7 @@ static NSMutableSet* hostList;
do { do {
appWasRemoved = NO; appWasRemoved = NO;
for (TemporaryApp* app in host.appList) { for (TemporaryApp* app in newHostAppList) {
appWasRemoved = YES; appWasRemoved = YES;
for (TemporaryApp* mergedApp in newList) { for (TemporaryApp* mergedApp in newList) {
if ([mergedApp.id isEqualToString:app.id]) { if ([mergedApp.id isEqualToString:app.id]) {
@@ -225,7 +226,7 @@ static NSMutableSet* hostList;
// Removing the app mutates the list we're iterating (which isn't legal). // Removing the app mutates the list we're iterating (which isn't legal).
// We need to jump out of this loop and restart enumeration. // We need to jump out of this loop and restart enumeration.
[host.appList removeObject:app]; [newHostAppList removeObject:app];
// It's important to remove the app record from the database // It's important to remove the app record from the database
// since we'll have a constraint violation now that appList // since we'll have a constraint violation now that appList
@@ -239,6 +240,8 @@ static NSMutableSet* hostList;
// Keep looping until the list is no longer being mutated // Keep looping until the list is no longer being mutated
} while (appWasRemoved); } while (appWasRemoved);
host.appList = newHostAppList;
[database updateAppsForExistingHost:host]; [database updateAppsForExistingHost:host];
// This host may be eligible for a shortcut now that the app list // This host may be eligible for a shortcut now that the app list