BoltsFramework / Bolts-ObjC

Bolts is a collection of low-level libraries designed to make developing mobile apps easier.
Other
5.64k stars 576 forks source link

Race Conditions #302

Open tealshift opened 7 years ago

tealshift commented 7 years ago

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 a BOOL 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.

jesusmateos1234 commented 3 years ago

@tealshift any update of this issue? @nlutsenko this also happens on Xcode 12.4