From 323249baa0f12642553feaa4cecd84b00cbeb463 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 17 Jan 2019 11:00:08 -0700 Subject: [PATCH] NSRunLoop methods should only be accessed on it's corresponding thread. --- SignalServiceKit/src/Util/NSTimer+OWS.h | 6 ---- SignalServiceKit/src/Util/NSTimer+OWS.m | 18 ------------ SignalServiceKit/src/Util/OWSOperation.m | 36 +++++++++++------------- 3 files changed, 17 insertions(+), 43 deletions(-) diff --git a/SignalServiceKit/src/Util/NSTimer+OWS.h b/SignalServiceKit/src/Util/NSTimer+OWS.h index 9aa7bebed..c530f209e 100644 --- a/SignalServiceKit/src/Util/NSTimer+OWS.h +++ b/SignalServiceKit/src/Util/NSTimer+OWS.h @@ -14,12 +14,6 @@ NS_ASSUME_NONNULL_BEGIN userInfo:(nullable id)userInfo repeats:(BOOL)repeats; -+ (NSTimer *)weakTimerWithTimeInterval:(NSTimeInterval)timeInterval - target:(id)target - selector:(SEL)selector - userInfo:(nullable id)userInfo - repeats:(BOOL)repeats; - @end NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Util/NSTimer+OWS.m b/SignalServiceKit/src/Util/NSTimer+OWS.m index 9b4ad739b..12eb39175 100644 --- a/SignalServiceKit/src/Util/NSTimer+OWS.m +++ b/SignalServiceKit/src/Util/NSTimer+OWS.m @@ -64,24 +64,6 @@ static void *kNSTimer_OWS_Proxy = &kNSTimer_OWS_Proxy; return timer; } -+ (NSTimer *)weakTimerWithTimeInterval:(NSTimeInterval)timeInterval - target:(id)target - selector:(SEL)selector - userInfo:(nullable id)userInfo - repeats:(BOOL)repeats -{ - NSTimerProxy *proxy = [NSTimerProxy new]; - proxy.target = target; - proxy.selector = selector; - NSTimer *timer = [NSTimer timerWithTimeInterval:timeInterval - target:proxy - selector:@selector(timerFired:) - userInfo:userInfo - repeats:repeats]; - [timer ows_setProxy:proxy]; - return timer; -} - @end NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Util/OWSOperation.m b/SignalServiceKit/src/Util/OWSOperation.m index e0c0e65a5..df6daf11f 100644 --- a/SignalServiceKit/src/Util/OWSOperation.m +++ b/SignalServiceKit/src/Util/OWSOperation.m @@ -192,25 +192,23 @@ NSString *const OWSOperationKeyIsFinished = @"isFinished"; self.remainingRetries--; - dispatch_sync(self.retryTimerSerialQueue, ^{ - OWSAssertDebug(self.retryTimer == nil); - [self.retryTimer invalidate]; - NSTimer *retryTimer = [NSTimer weakTimerWithTimeInterval:self.retryInterval - target:self - selector:@selector(runAnyQueuedRetry) - userInfo:nil - repeats:NO]; - - self.retryTimer = retryTimer; - - // The `scheduledTimerWith*` methods add the timer to the current thread's RunLoop. - // Since Operations typically run on a background thread, that would mean the background - // thread's RunLoop. However, the OS can spin down background threads if there's no work - // being done, so we run the risk of the timer's RunLoop being deallocated before it's - // fired. - // - // To ensure the timer's thread sticks around, we schedule it on the main RunLoop. - [NSRunLoop.mainRunLoop addTimer:retryTimer forMode:NSDefaultRunLoopMode]; + dispatch_async(dispatch_get_main_queue(), ^{ + dispatch_sync(self.retryTimerSerialQueue, ^{ + OWSAssertDebug(self.retryTimer == nil); + [self.retryTimer invalidate]; + // The `scheduledTimerWith*` methods add the timer to the current thread's RunLoop. + // Since Operations typically run on a background thread, that would mean the background + // thread's RunLoop. However, the OS can spin down background threads if there's no work + // being done, so we run the risk of the timer's RunLoop being deallocated before it's + // fired. + // + // To ensure the timer's thread sticks around, we schedule it while on the main RunLoop. + self.retryTimer = [NSTimer weakScheduledTimerWithTimeInterval:self.retryInterval + target:self + selector:@selector(runAnyQueuedRetry) + userInfo:nil + repeats:NO]; + }); }); }