-
-
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
SDImageCache diskImageExistsWithKey may leads dead lock #625
Comments
The only way that could happen is if you call The assumption was made that this would be unlikely called from that queue, however it does need to be on that queue since NSFileManager is not threadsafe and was created on the ioQueue. We could instead prevent the possibility of a deadlock by doing something similar to Seem reasonable? |
Hmmm ... I'm taking an interest because I'm getting deadlocks frequently at present. "The methods of the shared NSFileManager object can be called from multiple threads safely. However, if you use a delegate to receive notifications about the status of move, copy, remove, and link operations, you should create a unique instance of the file manager object, assign your delegate to that object, and use that file manager to initiate your operations." I can fix my problems by modifying SDWebImage to ignore the synchronous ioQueue. |
Interesting! Good catch. Seems that if you use the |
I'm seeing the same problem in my application. I fixed the problem by using the defaultManager for NSFileManager in the diskImageExistsWithKey method and removing the synchronous block (as mentioned above). |
Same problem here, and issue #507 is the same thing. Could we fix it? |
This is an ongoing issue for my project as well. |
I have also changed my version to use default manager to fix a 14 second deadlock I was experiencing:
Have not encountered any issues with initial testing and my App uses SDWebImage heavily. |
Yes, I think there really is a problem here and it's actually broader that this specific example. It's pretty easy to see how we can get to a deadlock here. If This can also happen in other places where dispatch_main_sync_safe is used to invoke callbacks ( In general I think it's pretty risky to invoke callbacks from a queue to main queue synchronously, if there are places where the main queue can enter the particular queue in a synchronous manner. To play it safe, think callbacks should rather be always dispatched asynchronously as a general rule (meaning 3a6d948 and any similar modifications should perhaps be reverted). |
Seems reasonable. Quick fix would be to just use the [NSFileManager Simple pull-request should do the trick :) On Mon, Mar 24, 2014 at 5:14 AM, Matej Bukovinski
|
- more appropriate than dispatch_main_sync_safe, since we’ll always be on the ioQueue when calling - prevents deadlock situation described in SDWebImage#625
I came up with a couple of fixes for SDImageCache, that hopefully improve things a bit. I guess that using the shared file manager would be ok here, however in my opinion, always using the serial I also think that using dispatch_async for the callbacks is more appropriate here, since we're always on the ioQueue and |
…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).
…ageExistsWithKey:]` 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:`
Fixed by commit 6e4fbaf. |
- more appropriate than dispatch_main_sync_safe, since we’ll always be on the ioQueue when calling - prevents deadlock situation described in SDWebImage#625
…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:`
call this method in main thread :
(BOOL)diskImageExistsWithKey:(NSString *)key
{
__block BOOL exists = NO;
dispatch_sync(_ioQueue, ^
{
exists = [_fileManager fileExistsAtPath:[self defaultCachePathForKey:key]];
});
return exists;
}
while SDImageCache ioQueue execute dispatch_main_sync_safe in method
-(NSOperation *)queryDiskCacheForKey:(NSString *)key done:(void (^)(UIImage *image, SDImageCacheType cacheType))doneBlock ,line 308.
So,Can we implement the method as follow :
(BOOL)diskImageExistsWithKey:(NSString *)key
{
NSFileManager *fileManager = [[NSFileManager alloc]init];
BOOL exists = [fileManager fileExistsAtPath:[self defaultCachePathForKey:key]];
return exists;
}
Thanks !
The text was updated successfully, but these errors were encountered: