Fixes race condition when installing app with app groups + extensions

This commit is contained in:
Riley Testut
2020-03-19 11:56:28 -07:00
parent 0d735431e9
commit 4fd2b448bd

View File

@@ -16,6 +16,8 @@ class FetchProvisioningProfilesOperation: ResultOperation<[String: ALTProvisioni
{ {
let context: AppOperationContext let context: AppOperationContext
private let appGroupsLock = NSLock()
init(context: AppOperationContext) init(context: AppOperationContext)
{ {
self.context = context self.context = context
@@ -346,16 +348,25 @@ extension FetchProvisioningProfilesOperation
} }
} }
// Dispatch onto global queue to prevent appGroupsLock deadlock.
DispatchQueue.global().async {
let adjustedGroupIdentifier = groupIdentifier + "." + team.identifier let adjustedGroupIdentifier = groupIdentifier + "." + team.identifier
// Ensure we're not concurrently fetching and updating app groups,
// which can lead to race conditions such as adding an app group twice.
self.appGroupsLock.lock()
ALTAppleAPI.shared.fetchAppGroups(for: team, session: session) { (groups, error) in ALTAppleAPI.shared.fetchAppGroups(for: team, session: session) { (groups, error) in
switch Result(groups, error) switch Result(groups, error)
{ {
case .failure(let error): completionHandler(.failure(error)) case .failure(let error):
case .success(let groups): self.appGroupsLock.unlock()
completionHandler(.failure(error))
case .success(let groups):
if let group = groups.first(where: { $0.groupIdentifier == adjustedGroupIdentifier }) if let group = groups.first(where: { $0.groupIdentifier == adjustedGroupIdentifier })
{ {
self.appGroupsLock.unlock()
finish(.success(group)) finish(.success(group))
} }
else else
@@ -364,12 +375,14 @@ extension FetchProvisioningProfilesOperation
let name = "AltStore " + groupIdentifier.replacingOccurrences(of: ".", with: " ") let name = "AltStore " + groupIdentifier.replacingOccurrences(of: ".", with: " ")
ALTAppleAPI.shared.addAppGroup(withName: name, groupIdentifier: adjustedGroupIdentifier, team: team, session: session) { (group, error) in ALTAppleAPI.shared.addAppGroup(withName: name, groupIdentifier: adjustedGroupIdentifier, team: team, session: session) { (group, error) in
self.appGroupsLock.unlock()
finish(Result(group, error)) finish(Result(group, error))
} }
} }
} }
} }
} }
}
func fetchProvisioningProfile(for appID: ALTAppID, team: ALTTeam, session: ALTAppleAPISession, completionHandler: @escaping (Result<ALTProvisioningProfile, Error>) -> Void) func fetchProvisioningProfile(for appID: ALTAppID, team: ALTTeam, session: ALTAppleAPISession, completionHandler: @escaping (Result<ALTProvisioningProfile, Error>) -> Void)
{ {