From 5a18c84529dd5cd9cd45c8689d55b62d3b73b54a Mon Sep 17 00:00:00 2001 From: Alexander Gaidukov Date: Mon, 5 Sep 2022 16:32:32 +0700 Subject: [PATCH] Synchronise getter and setter of the cancelled property of the SDWebImageCombinedOperation in order to eliminate data race. --- SDWebImage/Core/SDWebImageManager.m | 50 ++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/SDWebImage/Core/SDWebImageManager.m b/SDWebImage/Core/SDWebImageManager.m index 3b29632d..d5be68f6 100644 --- a/SDWebImage/Core/SDWebImageManager.m +++ b/SDWebImage/Core/SDWebImageManager.m @@ -17,7 +17,9 @@ static id _defaultImageCache; static id _defaultImageLoader; -@interface SDWebImageCombinedOperation () +@interface SDWebImageCombinedOperation () { + SD_LOCK_DECLARE(_cancelledLock); // a lock to keep the access to `cancelled` thread-safe +} @property (assign, nonatomic, getter = isCancelled) BOOL cancelled; @property (strong, nonatomic, readwrite, nullable) id loaderOperation; @@ -803,22 +805,38 @@ static id _defaultImageLoader; @implementation SDWebImageCombinedOperation -- (void)cancel { - @synchronized(self) { - if (self.isCancelled) { - return; - } - self.cancelled = YES; - if (self.cacheOperation) { - [self.cacheOperation cancel]; - self.cacheOperation = nil; - } - if (self.loaderOperation) { - [self.loaderOperation cancel]; - self.loaderOperation = nil; - } - [self.manager safelyRemoveOperationFromRunning:self]; +- (instancetype)init { + if (self = [super init]) { + SD_LOCK_INIT(_cancelledLock); } + + return self; +} + +- (BOOL)isCancelled { + BOOL isCancelled = NO; + SD_LOCK(_cancelledLock); + isCancelled = _cancelled; + SD_UNLOCK(_cancelledLock); + return isCancelled; +} + +- (void)cancel { + SD_LOCK(_cancelledLock); + if (_cancelled) { + return; + } + _cancelled = YES; + if (self.cacheOperation) { + [self.cacheOperation cancel]; + self.cacheOperation = nil; + } + if (self.loaderOperation) { + [self.loaderOperation cancel]; + self.loaderOperation = nil; + } + [self.manager safelyRemoveOperationFromRunning:self]; + SD_UNLOCK(_cancelledLock); } @end