Merge pull request #3403 from dreampiggy/revert_isCancelled_block_with_recursive

Fix the crash because of SDWebImageCombinedOperation recursive lock
This commit is contained in:
DreamPiggy 2022-09-19 18:20:06 +08:00 committed by GitHub
commit 524d4f53eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 31 deletions

View File

@ -29,6 +29,9 @@ typedef void(^SDInternalCompletionBlock)(UIImage * _Nullable image, NSData * _Nu
*/ */
- (void)cancel; - (void)cancel;
/// Whether the operation has been cancelled.
@property (nonatomic, assign, readonly, getter=isCancelled) BOOL cancelled;
/** /**
The cache operation from the image cache query The cache operation from the image cache query
*/ */

View File

@ -17,9 +17,7 @@
static id<SDImageCache> _defaultImageCache; static id<SDImageCache> _defaultImageCache;
static id<SDImageLoader> _defaultImageLoader; static id<SDImageLoader> _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 (assign, nonatomic, getter = isCancelled) BOOL cancelled;
@property (strong, nonatomic, readwrite, nullable) id<SDWebImageOperation> loaderOperation; @property (strong, nonatomic, readwrite, nullable) id<SDWebImageOperation> loaderOperation;
@ -805,39 +803,30 @@ static id<SDImageLoader> _defaultImageLoader;
@implementation SDWebImageCombinedOperation @implementation SDWebImageCombinedOperation
- (instancetype)init {
if (self = [super init]) {
SD_LOCK_INIT(_cancelledLock);
}
return self;
}
- (BOOL)isCancelled { - (BOOL)isCancelled {
BOOL isCancelled = NO; // Need recursive lock (user's cancel block may check isCancelled), do not use SD_LOCK
SD_LOCK(_cancelledLock); @synchronized (self) {
isCancelled = _cancelled; return _cancelled;
SD_UNLOCK(_cancelledLock); }
return isCancelled;
} }
- (void)cancel { - (void)cancel {
SD_LOCK(_cancelledLock); // Need recursive lock (user's cancel block may check isCancelled), do not use SD_LOCK
if (_cancelled) { @synchronized(self) {
SD_UNLOCK(_cancelledLock); if (_cancelled) {
return; 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];
} }
_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 @end