Ensure we're retaining all promises to completion

// FREEBIE
pull/1/head
Michael Kirk 8 years ago
parent dd3d338966
commit 2ec893d315

@ -100,6 +100,8 @@
453D28B71D32BA5F00D523F0 /* OWSDisplayedMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 453D28B61D32BA5F00D523F0 /* OWSDisplayedMessage.m */; }; 453D28B71D32BA5F00D523F0 /* OWSDisplayedMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 453D28B61D32BA5F00D523F0 /* OWSDisplayedMessage.m */; };
453D28BA1D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m in Sources */ = {isa = PBXBuildFile; fileRef = 453D28B91D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m */; }; 453D28BA1D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m in Sources */ = {isa = PBXBuildFile; fileRef = 453D28B91D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m */; };
453D28BB1D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m in Sources */ = {isa = PBXBuildFile; fileRef = 453D28B91D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m */; }; 453D28BB1D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m in Sources */ = {isa = PBXBuildFile; fileRef = 453D28B91D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m */; };
4542F0961EBB9E9A00C7EE92 /* Promise+retainUntilComplete.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4542F0951EBB9E9A00C7EE92 /* Promise+retainUntilComplete.swift */; };
4542F0971EBB9E9A00C7EE92 /* Promise+retainUntilComplete.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4542F0951EBB9E9A00C7EE92 /* Promise+retainUntilComplete.swift */; };
45464DBC1DFA041F001D3FD6 /* DataChannelMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45464DBB1DFA041F001D3FD6 /* DataChannelMessage.swift */; }; 45464DBC1DFA041F001D3FD6 /* DataChannelMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45464DBB1DFA041F001D3FD6 /* DataChannelMessage.swift */; };
45666EC61D99483D008FE134 /* OWSAvatarBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 45666EC51D99483D008FE134 /* OWSAvatarBuilder.m */; }; 45666EC61D99483D008FE134 /* OWSAvatarBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 45666EC51D99483D008FE134 /* OWSAvatarBuilder.m */; };
45666EC91D994C0D008FE134 /* OWSGroupAvatarBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 45666EC81D994C0D008FE134 /* OWSGroupAvatarBuilder.m */; }; 45666EC91D994C0D008FE134 /* OWSGroupAvatarBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 45666EC81D994C0D008FE134 /* OWSGroupAvatarBuilder.m */; };
@ -437,8 +439,8 @@
34B3F86E1E8DF1700035BE1A /* SignalsNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalsNavigationController.m; sourceTree = "<group>"; }; 34B3F86E1E8DF1700035BE1A /* SignalsNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalsNavigationController.m; sourceTree = "<group>"; };
34B3F86F1E8DF1700035BE1A /* SignalsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SignalsViewController.h; sourceTree = "<group>"; }; 34B3F86F1E8DF1700035BE1A /* SignalsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SignalsViewController.h; sourceTree = "<group>"; };
34B3F8701E8DF1700035BE1A /* SignalsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalsViewController.m; sourceTree = "<group>"; }; 34B3F8701E8DF1700035BE1A /* SignalsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalsViewController.m; sourceTree = "<group>"; };
34B3F8981E8DF1B90035BE1A /* TSMessageAdapterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSMessageAdapterTest.m; sourceTree = "<group>"; };
34B3F89A1E8DF3270035BE1A /* BlockListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockListViewController.h; sourceTree = "<group>"; }; 34B3F89A1E8DF3270035BE1A /* BlockListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockListViewController.h; sourceTree = "<group>"; };
34B3F8981E8DF1B90035BE1A /* TSMessageAdapterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSMessageAdapterTest.m; sourceTree = "<group>"; };
34B3F89B1E8DF3270035BE1A /* BlockListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BlockListViewController.m; sourceTree = "<group>"; }; 34B3F89B1E8DF3270035BE1A /* BlockListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BlockListViewController.m; sourceTree = "<group>"; };
34B3F89D1E8DF5490035BE1A /* OWSTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSTableViewController.h; sourceTree = "<group>"; }; 34B3F89D1E8DF5490035BE1A /* OWSTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSTableViewController.h; sourceTree = "<group>"; };
34B3F89E1E8DF5490035BE1A /* OWSTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSTableViewController.m; sourceTree = "<group>"; }; 34B3F89E1E8DF5490035BE1A /* OWSTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSTableViewController.m; sourceTree = "<group>"; };
@ -489,6 +491,7 @@
453D28B61D32BA5F00D523F0 /* OWSDisplayedMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDisplayedMessage.m; sourceTree = "<group>"; }; 453D28B61D32BA5F00D523F0 /* OWSDisplayedMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDisplayedMessage.m; sourceTree = "<group>"; };
453D28B81D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessagesBubblesSizeCalculator.h; sourceTree = "<group>"; }; 453D28B81D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessagesBubblesSizeCalculator.h; sourceTree = "<group>"; };
453D28B91D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSMessagesBubblesSizeCalculator.m; sourceTree = "<group>"; }; 453D28B91D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSMessagesBubblesSizeCalculator.m; sourceTree = "<group>"; };
4542F0951EBB9E9A00C7EE92 /* Promise+retainUntilComplete.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Promise+retainUntilComplete.swift"; sourceTree = "<group>"; };
45464DBB1DFA041F001D3FD6 /* DataChannelMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataChannelMessage.swift; sourceTree = "<group>"; }; 45464DBB1DFA041F001D3FD6 /* DataChannelMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataChannelMessage.swift; sourceTree = "<group>"; };
454B35071D08EED80026D658 /* mk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = mk; path = translations/mk.lproj/Localizable.strings; sourceTree = "<group>"; }; 454B35071D08EED80026D658 /* mk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = mk; path = translations/mk.lproj/Localizable.strings; sourceTree = "<group>"; };
45666EC41D99483D008FE134 /* OWSAvatarBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSAvatarBuilder.h; sourceTree = "<group>"; }; 45666EC41D99483D008FE134 /* OWSAvatarBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSAvatarBuilder.h; sourceTree = "<group>"; };
@ -1246,6 +1249,7 @@
76EB04FB18170B33006006FC /* Util.h */, 76EB04FB18170B33006006FC /* Util.h */,
45F170D51E315310003FC1F2 /* Weak.swift */, 45F170D51E315310003FC1F2 /* Weak.swift */,
45F170CB1E310E22003FC1F2 /* WeakTimer.swift */, 45F170CB1E310E22003FC1F2 /* WeakTimer.swift */,
4542F0951EBB9E9A00C7EE92 /* Promise+retainUntilComplete.swift */,
); );
path = util; path = util;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1990,6 +1994,7 @@
34B3F8791E8DF1700035BE1A /* CountryCodeViewController.m in Sources */, 34B3F8791E8DF1700035BE1A /* CountryCodeViewController.m in Sources */,
4CE0E3771B954546007210CF /* TSAnimatedAdapter.m in Sources */, 4CE0E3771B954546007210CF /* TSAnimatedAdapter.m in Sources */,
4531C9C41DD8E6D800F08304 /* JSQMessagesCollectionViewCell+OWS.m in Sources */, 4531C9C41DD8E6D800F08304 /* JSQMessagesCollectionViewCell+OWS.m in Sources */,
4542F0961EBB9E9A00C7EE92 /* Promise+retainUntilComplete.swift in Sources */,
4516E3FF1DD2193B00DC4206 /* OWS101ExistingUsersBlockOnIdentityChange.m in Sources */, 4516E3FF1DD2193B00DC4206 /* OWS101ExistingUsersBlockOnIdentityChange.m in Sources */,
4505C2BF1E648EA300CEBF41 /* ExperienceUpgrade.swift in Sources */, 4505C2BF1E648EA300CEBF41 /* ExperienceUpgrade.swift in Sources */,
45387B041E36D650005D00B3 /* OWS102MoveLoggingPreferenceToUserDefaults.m in Sources */, 45387B041E36D650005D00B3 /* OWS102MoveLoggingPreferenceToUserDefaults.m in Sources */,
@ -2169,6 +2174,7 @@
45FBC5D21DF8592E00E9B410 /* SignalCall.swift in Sources */, 45FBC5D21DF8592E00E9B410 /* SignalCall.swift in Sources */,
451A13B21E13DED2000A50FD /* CallNotificationsAdapter.swift in Sources */, 451A13B21E13DED2000A50FD /* CallNotificationsAdapter.swift in Sources */,
45C681B81D305A580050903A /* OWSCall.m in Sources */, 45C681B81D305A580050903A /* OWSCall.m in Sources */,
4542F0971EBB9E9A00C7EE92 /* Promise+retainUntilComplete.swift in Sources */,
45855F381D9498A40084F340 /* OWSContactAvatarBuilder.m in Sources */, 45855F381D9498A40084F340 /* OWSContactAvatarBuilder.m in Sources */,
45DF5DF31DDB843F00C936C7 /* CompareSafetyNumbersActivity.swift in Sources */, 45DF5DF31DDB843F00C936C7 /* CompareSafetyNumbersActivity.swift in Sources */,
456AC8341E3A775E00A3C7FC /* Weak.swift in Sources */, 456AC8341E3A775E00A3C7FC /* Weak.swift in Sources */,

@ -12,8 +12,6 @@ class SyncPushTokensJob: NSObject {
let accountManager: AccountManager let accountManager: AccountManager
let preferences: PropertyListPreferences let preferences: PropertyListPreferences
var uploadOnlyIfStale = true var uploadOnlyIfStale = true
// useful to ensure promise runs to completion
var retainCycle: SyncPushTokensJob?
required init(pushManager: PushManager, accountManager: AccountManager, preferences: PropertyListPreferences) { required init(pushManager: PushManager, accountManager: AccountManager, preferences: PropertyListPreferences) {
self.pushManager = pushManager self.pushManager = pushManager
@ -32,14 +30,12 @@ class SyncPushTokensJob: NSObject {
func run() -> Promise<Void> { func run() -> Promise<Void> {
Logger.debug("\(TAG) Starting.") Logger.debug("\(TAG) Starting.")
// Make sure we don't GC until completion.
self.retainCycle = self
// Required to potentially prompt user for notifications settings // Required to potentially prompt user for notifications settings
// before `requestPushTokens` will return. // before `requestPushTokens` will return.
self.pushManager.validateUserNotificationSettings() self.pushManager.validateUserNotificationSettings()
return self.requestPushTokens().then { (pushToken: String, voipToken: String) in let runPromise: Promise<Void> = self.requestPushTokens().then { (pushToken: String, voipToken: String) in
var shouldUploadTokens = !self.uploadOnlyIfStale var shouldUploadTokens = !self.uploadOnlyIfStale
if self.preferences.getPushToken() != pushToken || self.preferences.getVoipToken() != voipToken { if self.preferences.getPushToken() != pushToken || self.preferences.getVoipToken() != voipToken {
Logger.debug("\(self.TAG) push tokens changed.") Logger.debug("\(self.TAG) push tokens changed.")
@ -56,9 +52,10 @@ class SyncPushTokensJob: NSObject {
Logger.info("\(self.TAG) Recording tokens locally.") Logger.info("\(self.TAG) Recording tokens locally.")
return self.recordNewPushTokens(pushToken:pushToken, voipToken:voipToken) return self.recordNewPushTokens(pushToken:pushToken, voipToken:voipToken)
} }
}.always {
self.retainCycle = nil
} }
runPromise.retainUntilComplete()
return runPromise
} }
private func requestPushTokens() -> Promise<(pushToken: String, voipToken: String)> { private func requestPushTokens() -> Promise<(pushToken: String, voipToken: String)> {

@ -125,7 +125,7 @@ protocol CallServiceObserver: class {
didSet { didSet {
AssertIsOnMainThread() AssertIsOnMainThread()
Logger.debug("\(self.TAG) .peerConnectionClient setter: \(oldValue != nil) -> \(peerConnectionClient != nil) \(peerConnectionClient)") Logger.debug("\(self.TAG) .peerConnectionClient setter: \(oldValue != nil) -> \(peerConnectionClient != nil) \(String(describing: peerConnectionClient))")
} }
} }
@ -141,7 +141,7 @@ protocol CallServiceObserver: class {
updateIsVideoEnabled() updateIsVideoEnabled()
updateLockTimerEnabling() updateLockTimerEnabling()
Logger.debug("\(self.TAG) .call setter: \(oldValue != nil) -> \(call != nil) \(call)") Logger.debug("\(self.TAG) .call setter: \(oldValue != nil) -> \(call != nil) \(String(describing: call))")
for observer in observers { for observer in observers {
observer.value?.didUpdateCall(call:call) observer.value?.didUpdateCall(call:call)
@ -368,9 +368,10 @@ protocol CallServiceObserver: class {
if pendingIceUpdateMessages.count > 0 { if pendingIceUpdateMessages.count > 0 {
let callMessage = OWSOutgoingCallMessage(thread: thread, iceUpdateMessages: pendingIceUpdateMessages) let callMessage = OWSOutgoingCallMessage(thread: thread, iceUpdateMessages: pendingIceUpdateMessages)
_ = messageSender.sendCallMessage(callMessage).catch { error in let sendPromise = messageSender.sendCallMessage(callMessage).catch { error in
Logger.error("\(self.TAG) failed to send ice updates in \(#function) with error: \(error)") Logger.error("\(self.TAG) failed to send ice updates in \(#function) with error: \(error)")
} }
sendPromise.retainUntilComplete()
} }
guard let peerConnectionClient = self.peerConnectionClient else { guard let peerConnectionClient = self.peerConnectionClient else {
@ -379,7 +380,7 @@ protocol CallServiceObserver: class {
} }
let sessionDescription = RTCSessionDescription(type: .answer, sdp: sessionDescription) let sessionDescription = RTCSessionDescription(type: .answer, sdp: sessionDescription)
_ = peerConnectionClient.setRemoteSessionDescription(sessionDescription).then { let setDescriptionPromise = peerConnectionClient.setRemoteSessionDescription(sessionDescription).then {
Logger.debug("\(self.TAG) successfully set remote description") Logger.debug("\(self.TAG) successfully set remote description")
}.catch { error in }.catch { error in
if let callError = error as? CallError { if let callError = error as? CallError {
@ -389,6 +390,7 @@ protocol CallServiceObserver: class {
self.handleFailedCall(failedCall: call, error: externalError) self.handleFailedCall(failedCall: call, error: externalError)
} }
} }
setDescriptionPromise.retainUntilComplete()
} }
/** /**
@ -424,7 +426,8 @@ protocol CallServiceObserver: class {
let busyMessage = OWSCallBusyMessage(callId: call.signalingId) let busyMessage = OWSCallBusyMessage(callId: call.signalingId)
let callMessage = OWSOutgoingCallMessage(thread: thread, busyMessage: busyMessage) let callMessage = OWSOutgoingCallMessage(thread: thread, busyMessage: busyMessage)
_ = messageSender.sendCallMessage(callMessage) let sendPromise = messageSender.sendCallMessage(callMessage)
sendPromise.retainUntilComplete()
handleMissedCall(call, thread: thread) handleMissedCall(call, thread: thread)
} }
@ -622,7 +625,8 @@ protocol CallServiceObserver: class {
if self.sendIceUpdatesImmediately { if self.sendIceUpdatesImmediately {
let callMessage = OWSOutgoingCallMessage(thread: thread, iceUpdateMessage: iceUpdateMessage) let callMessage = OWSOutgoingCallMessage(thread: thread, iceUpdateMessage: iceUpdateMessage)
_ = self.messageSender.sendCallMessage(callMessage) let sendPromise = self.messageSender.sendCallMessage(callMessage)
sendPromise.retainUntilComplete()
} else { } else {
// For outgoing messages, we wait to send ice updates until we're sure client received our call message. // For outgoing messages, we wait to send ice updates until we're sure client received our call message.
// e.g. if the client has blocked our message due to an identity change, we'd otherwise // e.g. if the client has blocked our message due to an identity change, we'd otherwise
@ -880,11 +884,12 @@ protocol CallServiceObserver: class {
// If the call hasn't started yet, we don't have a data channel to communicate the hang up. Use Signal Service Message. // If the call hasn't started yet, we don't have a data channel to communicate the hang up. Use Signal Service Message.
let hangupMessage = OWSCallHangupMessage(callId: call.signalingId) let hangupMessage = OWSCallHangupMessage(callId: call.signalingId)
let callMessage = OWSOutgoingCallMessage(thread: thread, hangupMessage: hangupMessage) let callMessage = OWSOutgoingCallMessage(thread: thread, hangupMessage: hangupMessage)
_ = self.messageSender.sendCallMessage(callMessage).then { let sendPromise = self.messageSender.sendCallMessage(callMessage).then {
Logger.debug("\(self.TAG) successfully sent hangup call message to \(thread)") Logger.debug("\(self.TAG) successfully sent hangup call message to \(thread)")
}.catch { error in }.catch { error in
Logger.error("\(self.TAG) failed to send hangup call message to \(thread) with error: \(error)") Logger.error("\(self.TAG) failed to send hangup call message to \(thread) with error: \(error)")
} }
sendPromise.retainUntilComplete()
terminateCall() terminateCall()
} }

@ -239,7 +239,9 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
// We can't wait for long before fulfilling the CXAction, else CallKit will show a "Failed Call". We don't // We can't wait for long before fulfilling the CXAction, else CallKit will show a "Failed Call". We don't
// actually need to wait for the outcome of the handleOutgoingCall promise, because it handles any errors by // actually need to wait for the outcome of the handleOutgoingCall promise, because it handles any errors by
// manually failing the call. // manually failing the call.
_ = self.callService.handleOutgoingCall(call) let callPromise = self.callService.handleOutgoingCall(call)
callPromise.retainUntilComplete()
action.fulfill() action.fulfill()
self.provider.reportOutgoingCall(with: call.localId, startedConnectingAt: nil) self.provider.reportOutgoingCall(with: call.localId, startedConnectingAt: nil)

@ -0,0 +1,20 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
import PromiseKit
public extension Promise {
/**
* Sometimes there isn't a straight forward candidate to retain a promise, in that case we tell the
* promise to self retain, until it completes to avoid the risk it's GC'd before completion.
*/
func retainUntilComplete() {
// Unfortunately, there is (currently) no way to surpress the
// compiler warning: "Variable 'retainCycle' was written to, but never read"
var retainCycle: Promise<T>? = self
self.always {
retainCycle = nil
}
}
}
Loading…
Cancel
Save