diff --git a/SignalServiceKit/src/Loki/API/LokiAPI+SwarmAPI.swift b/SignalServiceKit/src/Loki/API/LokiAPI+SwarmAPI.swift index 61ec13fce..50d363008 100644 --- a/SignalServiceKit/src/Loki/API/LokiAPI+SwarmAPI.swift +++ b/SignalServiceKit/src/Loki/API/LokiAPI+SwarmAPI.swift @@ -32,6 +32,7 @@ public extension LokiAPI { // MARK: Internal API internal static func getRandomSnode() -> Promise { + // All of this has to happen on DispatchQueue.global() due to the way OWSMessageManager works if randomSnodePool.isEmpty { let target = seedNodePool.randomElement()! let url = URL(string: "\(target)/json_rpc")! @@ -49,7 +50,7 @@ public extension LokiAPI { ] ]) print("[Loki] Invoking get_n_service_nodes on \(target).") - return TSNetworkManager.shared().perform(request).map(on: DispatchQueue.global()) { intermediate in + return TSNetworkManager.shared().perform(request, withCompletionQueue: DispatchQueue.global()).map(on: DispatchQueue.global()) { intermediate in let rawResponse = intermediate.responseObject guard let json = rawResponse as? JSON, let intermediate = json["result"] as? JSON, let rawTargets = intermediate["service_node_states"] as? [JSON] else { throw LokiAPIError.randomSnodePoolUpdatingFailed } randomSnodePool = try Set(rawTargets.flatMap { rawTarget in @@ -61,7 +62,7 @@ public extension LokiAPI { }) // randomElement() uses the system's default random generator, which is cryptographically secure return randomSnodePool.randomElement()! - }.recover { error -> Promise in + }.recover(on: DispatchQueue.global()) { error -> Promise in print("[Loki] Failed to contact seed node at: \(target).") throw error }.retryingIfNeeded(maxRetryCount: 16) // The seed nodes have historically been unreliable diff --git a/SignalServiceKit/src/Loki/API/LokiFileServerProxy.swift b/SignalServiceKit/src/Loki/API/LokiFileServerProxy.swift index 05d7f1fd2..a291edcf0 100644 --- a/SignalServiceKit/src/Loki/API/LokiFileServerProxy.swift +++ b/SignalServiceKit/src/Loki/API/LokiFileServerProxy.swift @@ -44,6 +44,7 @@ internal class LokiFileServerProxy : LokiHTTPClient { } internal func performLokiFileServerNSURLRequest(_ request: NSURLRequest, withCompletionQueue queue: DispatchQueue = DispatchQueue.main) -> LokiAPI.RawResponsePromise { + // All of this has to happen on DispatchQueue.global() due to the way OWSMessageManager works var headers = getCanonicalHeaders(for: request) return Promise { [server = self.server, keyPair = self.keyPair, httpSession = self.httpSession] seal in DispatchQueue.global().async { @@ -116,9 +117,9 @@ internal class LokiFileServerProxy : LokiHTTPClient { let uncheckedJSON = try? JSONSerialization.jsonObject(with: uncheckedJSONAsData, options: .allowFragments) as? JSON guard let json = uncheckedJSON else { throw HTTPError.networkError(code: -1, response: nil, underlyingError: Error.proxyResponseParsingFailed) } return json - }.done { rawResponse in + }.done(on: DispatchQueue.global()) { rawResponse in seal.fulfill(rawResponse) - }.catch { error in + }.catch(on: DispatchQueue.global()) { error in print("[Loki] File server proxy request failed with error: \(error.localizedDescription).") seal.reject(HTTPError.from(error: error) ?? error) } diff --git a/SignalServiceKit/src/Loki/API/LokiHttpClient.swift b/SignalServiceKit/src/Loki/API/LokiHttpClient.swift index 202059f9b..8f9670f17 100644 --- a/SignalServiceKit/src/Loki/API/LokiHttpClient.swift +++ b/SignalServiceKit/src/Loki/API/LokiHttpClient.swift @@ -10,6 +10,7 @@ internal class LokiHTTPClient { securityPolicy.validatesDomainName = false result.securityPolicy = securityPolicy result.responseSerializer = AFHTTPResponseSerializer() + result.completionQueue = DispatchQueue.global() // All of this has to happen on DispatchQueue.global() due to the way OWSMessageManager works return result }() diff --git a/SignalServiceKit/src/Messages/OWSMessageManager.m b/SignalServiceKit/src/Messages/OWSMessageManager.m index b6ad356a1..db0bdccb4 100644 --- a/SignalServiceKit/src/Messages/OWSMessageManager.m +++ b/SignalServiceKit/src/Messages/OWSMessageManager.m @@ -1406,7 +1406,7 @@ NS_ASSUME_NONNULL_BEGIN }).catchOn(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(NSError *error) { dispatch_semaphore_signal(semaphore); }) retainUntilComplete]; - dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 4 * NSEC_PER_SEC)); + dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC)); } if (groupId.length > 0) {