-[BFTask waitUntilFinished] does not account for spurious thread wakeup
Created by: toddreed
See https://en.wikipedia.org/wiki/Spurious_wakeup for a description of "spurious wakeup". This seems to apply to NSCondition
, as Apple's documentation (Threading Programming Guide) states:
Due to the subtleties involved in implementing operating systems, condition locks are permitted to return with spurious success even if they were not actually signaled by your code. To avoid problems caused by these spurious signals, you should always use a predicate in conjunction with your condition lock.
(The reference documentation for NSCondition
also touches on this topic.)
I think something like this may be more correct:
- (void)waitUntilFinished {
if ([NSThread isMainThread]) {
[self warnOperationOnMainThread];
}
@synchronized (self.lock) {
if (self.completed) {
return;
}
[self.condition lock];
}
while (YES) {
[self.condition wait];
@synchronized (self.lock) {
if (self.completed)
break;
}
}
[self.condition unlock];
}
Alternately, using dispatch_semaphore_t
may provided a simpler implementation.
(Note that I have not actually observed a spurious wakeup. I don't know if this is a possibility on iOS.)