Race Conditions
Issue reported in Parse SDK GitHub: https://github.com/parse-community/Parse-SDK-iOS-OSX/issues/1175 Insights courtesy of @flovilmart :
Seems that the issue is in Bolts and not the Parse SDK. I ran the thread sanitizer and realized this:
Upon callback, setting the result on a particular thread
- (BOOL)trySetResult:(nullable id)result { @synchronized(self.lock) { if (self.completed) { return NO; } self.completed = YES; // <-- HERE _result = result; [self runContinuations]; return YES; } }
when a task is marked waitUntilFinished
- (void)waitUntilFinished { if ([NSThread isMainThread]) { [self warnOperationOnMainThread]; } @synchronized(self.lock) { if (self.completed) { return; } [self.condition lock]; } // TODO: (nlutsenko) Restructure this to use Bolts-Swift thread access synchronization architecture // In the meantime, it's absolutely safe to get `_completed` aka an ivar, as long as it's a `BOOL` aka less than word size. while (!_completed) { // <- READ data from there. [self.condition wait]; } [self.condition unlock]; }
Also there seems to be a note about it:
// TODO: (nlutsenko) Restructure this to use Bolts-Swift thread access synchronization architecture // In the meantime, it's absolutely safe to get
_completed
aka an ivar, as long as it's aBOOL
aka less than word size.We see other data races in bolts related to the concurrency model employed, mostly read on BOOL completed that are concurrent and not on the same thread.