SDWebImage: AVMetadataItemValueRequest & SDWebImageManager.load hang
New Issue Checklist
- [ X] I have read and understood the CONTRIBUTING guide
- [ X] I have read the Documentation
- [ X] I have searched for a similar issue in the project and found none
Issue Info
Info | Value |
---|---|
Platform Name | ios |
Platform Version | 14.0 - 16.2 |
SDWebImage Version | 5.12.1 |
Integration Method | cocoapods |
Xcode Version | 14.2 |
Repro rate | all the time (100%) |
Repro with our demo prj | don’t know yet |
Demo project link | none |
Issue Description and Steps
- iOS application with AVKit, SDWebImage (cocoapods)
- Lazy load artwork like that:
extension AVMetadataItem {
static func artwork(url: URL, placeholder: UIImage?) -> AVMetadataItem {
let art = AVMutableMetadataItem()
art.identifier = .commonIdentifierArtwork
art.dataType = kCMMetadataBaseDataType_PNG as String
art.extendedLanguageTag = "und"
return AVMetadataItem(propertiesOf: art) { request in
SDWebImageManager.shared
.loadImage(with: url, context: [:], progress: nil) { image, _, error, _, _, _ in
// no call here at all, hang application before this callback
let cover: UIImage?
if let image = image {
cover = image
} else {
cover = placeholder
}
guard let data = cover?.pngData() else {
request.respond(error: CustomError.loadImageFailed)
return
}
request.respond(value: data as NSData)
}
}
}
I found some place in code there is hang started in file SDImageCache.m
:
if (doneBlock) {
if (shouldQueryDiskSync) {
doneBlock(diskImage, diskData, SDImageCacheTypeDisk);
} else {
dispatch_async(dispatch_get_main_queue(), ^{ // <<< HERE
doneBlock(diskImage, diskData, SDImageCacheTypeDisk);
});
}
}
This hang happen only when call load image in AVMetadataItem function for lazy load, nothing hangs when load by URLSession.shared Can’t yet understand any reason for that 😦
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 20 (14 by maintainers)
Yes. SDWebImage currently hardcode to callback to main queue, this cause issue.
URLSession’s callback queue is control by you. By defaults is just callback in a random global queue, if you don’t dispatch it into main queue (which is already been block by AVKit), nothing worng happended.
I think this is because that the SDImageCache’s callback queue is
main queue
.However, the main queue is blocked by
AVFCore -[AVLazyValueLoadingMetadataItem _waitForLoadingOfValueDependentKey:]:
The caller queue is
AVFCore __84-[AVLazyValueLoadingMetadataItem loadValuesAsynchronouslyForKeys:completionHandler:]_block_invoke_3 ()
, and enqueue into SDImageCache (which isqueue 2
, but this actually does not effect the result)Did you get it ?
The problem occurs because:
main queue
wait forqueue 8
queue 8
callSDWebImageManager
to query cachemain queue
main queue
waitqueue 8
waitmain queue