-
-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixed deadlocks, completion blocks async, race condition on cancel #781
Conversation
…che diskImageExistsWithKey:]` method. Based on the Apple doc for NSFileManager, using the defaultManager without the dispatch on the ioQueue to avoid the deadlocks. This instance is thread safe. Also created an async variant of this method `[SDImageCache diskImageExistsWithKey:completion:]` For consistency, added async methods in `SDWebImageManager` `cachedImageExistsForURL:completion:` and `diskImageExistsForURL:completion:`
…l queue is an anti pattern, as it can lead to deadlocks. I replaced all the dispatch_main_sync_safe with dispatch_main_async_safe, based on the fact that the completion blocks are not returning anything, so we don't need to wait for them to finish. The biggest change (architectural) is that the completion block will no longer be executed inside the operation. But that is not an issue, as NSOperation does the same (completion block gets called after operation isFinished).
…ne operation is cancelled, the completion block must not be called, otherwise it might race with a newer completion for the same object
Guys, could you please review this? Especially @rs |
I initially tried to have dispatch_sync whenever possible as async delays the processing and slows down the display of images. |
Ok, I will do some profiling for sync vs async. |
I profiled a bit the sync vs async solutions, using an iPhone 4. I think the async one works better (as I would have expected), as it doesn't block any queue. It doesn't make sense why in the async version, the displaying would be slowed down. We are just registering a block for execution on the main queue, the only difference is if The only issue that popped on the async solution were some crashes inside @rs I think this is the only major showstopper for the 3.7.0 that we are being asked to release asap. |
Let go with async. We'll see if we get complaints :) |
I think the important thing to keep with async calls is that (memory) cache hits get returned in the same run loop iteration. This way we don't get any image flickering going on for this operation, that really should be instantaneous. Putting it another way. If I call |
Yes, the whole sync dance is about not delaying the cache check so UI doesn't have a chance to redraw. We may find a better way. |
Guys, I've given this more thought and I think the safest way to do this is:
This was due to the impossibility to predict the impact of changing those sync calls to async and the need to release the 3.7.0 version that a lot of developers are asking for. |
…it, so we added a check for operation and key
|
UPDATE: Hmm, I'm debugging further and I think it's a different issue. Let me investigate and get back to you. Not sure what's causing it, but definitely
is not calling the completion handler on some instances. This problem surfaced when updating from SDWebImage 3.6 to 3.7.1, but not sure which change exactly started to make it happen. We are heavily using the |
Hey guys I don't know if you guys are still focusing on the issue. Actually I'm not involving with any issues here, just feeling curious about the After reading the explanations from @matej and @rs , and the great example about But talking about the UI redrawing, is the main thread just here waiting for memory cache returns back and will draw the image once the image comes back from memory, immediately? There are still lot of time and chances for UI to redraw between querying cache and sending back the And what if the Please let me know if I missed something or there was any misunderstanding. Thanks! |
…e-vs-main-thread/, background queue can execute code on the main thread, so we need to check for the main queue to assure safety
… with `dispatch_main_async_safe`, so we no longer `dispatch_sync` on the main queue that can create issues.
…bImageDownloaderOperation` are called on the main queue. Created 2 methods to simplify the code for calling the completions
…ager` is called on the main queue. Created 2 methods to simplify the code for calling the completions
Redone this via commits 062e50a f7e8246 c77adf4 265ace4 0c47bc3 on the 4.x branch. Same stuff: replaced all sync calls to the completion with async, cleaned up the code a bit. Another important change is based on http://blog.benjamin-encz.de/post/main-queue-vs-main-thread. This article states that the main thread may execute code from other queues than the main queue, so we actually want to check for main queue to assure our UIKit operations. |
@croath I see your point, but I feel safer with the async code, since we have a history of locking here and there. Take a look and let me know what you think. |
@bpoplauschi Awesome! Yep the safety, just what I was talking about. So that I asked about why |
Fixed issues #625 #507 aka deadlocks (replaces #509)
[SDImageCache diskImageExistsWithKey:]
method. Based on the Apple doc forNSFileManager
, using thedefaultManager
without the dispatch on theioQueue
to avoid the deadlocks. This instance is thread safe. Also created an async variant of this method[SDImageCache diskImageExistsWithKey:completion:]
For consistency, added async methods in
SDWebImageManager
cachedImageExistsForURL:completion:
anddiskImageExistsForURL:completion:
dispatch_sync
on a serial queue is an anti pattern, as it can lead to deadlocks. I replaced all thedispatch_main_sync_safe
withdispatch_main_async_safe
, based on the fact that the completion blocks are not returning anything, so we don't need to wait for them to finish.NSOperation
does the same (completion block gets called after operationisFinished
).Fixed race condition In SDWebImageManager (replaces #699)