title: SIGABRT crash because of SDWebImageCache
body: <p>I am getting this crash log (getting it from users, cannot reproduce it):</p>
  
  <pre><code>Threads
  _________________________________
  Thread: Unknown Name (Crashed)
  0     libsystem_kernel.dylib                0x382dd1fc __pthread_kill + 8
  1     libsystem_c.dylib                     0x3828dffd abort + 77
  2     libc++abi.dylib                       0x375bccd7 abort_message + 75
  3     libc++abi.dylib                       0x375d320d _ZSt11__terminatePFvvE + 149
  4     libc++abi.dylib                       0x375d2d2d __cxa_increment_exception_refcount + 1
  5     libobjc.A.dylib                       0x37d1e7f7 objc_exception_rethrow + 43
  6     CoreFoundation                        0x2d811c9d CFRunLoopRunSpecific + 641
  7     CoreFoundation                        0x2d811a0b CFRunLoopRunInMode + 107
  8     GraphicsServices                      0x32538283 GSEventRunModal + 139
  9     UIKit                                 0x300b5049 UIApplicationMain + 1137
  10   Paok FC                                0x000c6723 main (main.m:12)
  
  Thread: Unknown Name
  0     libsystem_kernel.dylib                0x382ca83c kevent64 + 24
  1     libdispatch.dylib                     0x3820af9b _dispatch_mgr_thread$VARIANT$mp + 39
  
  Thread: Unknown Name
  0     libsystem_kernel.dylib                0x382ddc7c __workq_kernreturn + 8
  
  Thread: Unknown Name
  0     libsystem_kernel.dylib                0x382caadc semaphore_wait_trap + 8
  1     libdispatch.dylib                     0x38207a17 _dispatch_barrier_sync_f_slow + 139
  2     Paok FC                               0x0010c369 __42-[SDImageCache queryDiskCacheForKey:done:]_block_invoke (SDImageCache.m:308)
  3     libdispatch.dylib                     0x38201d1b _dispatch_call_block_and_release + 11
  4     libdispatch.dylib                     0x38208273 _dispatch_queue_drain$VARIANT$mp + 375
  5     libdispatch.dylib                     0x3820806b _dispatch_queue_invoke$VARIANT$mp + 43
  6     libdispatch.dylib                     0x38208ce1 _dispatch_root_queue_drain + 77
  7     libdispatch.dylib                     0x38208f59 _dispatch_worker_thread2 + 57
  8     libsystem_pthread.dylib               0x38343dbf _pthread_wqthread + 299
  
  Thread: Unknown Name
  0     libsystem_kernel.dylib                0x382caa8c mach_msg_trap + 20
  1     CoreFoundation                        0x2d8a87c3 __CFRunLoopServiceMachPort + 155
  2     CoreFoundation                        0x2d8a6ee9 __CFRunLoopRun + 785
  3     CoreFoundation                        0x2d811c27 CFRunLoopRunSpecific + 523
  4     CoreFoundation                        0x2d811a0b CFRunLoopRunInMode + 107
  5     Foundation                            0x2e24c2f7 +[NSURLConnection(Loader) _resourceLoadLoop:] + 319
  6     Foundation                            0x2e2c1c87 __NSThread__main__ + 1063
  7     libsystem_pthread.dylib               0x38345c1d _pthread_body + 141
  8     libsystem_pthread.dylib               0x38345b8f _pthread_start + 103
  
  Thread: Unknown Name
  0     libsystem_kernel.dylib                0x382dd440 __select + 20
  1     libsystem_pthread.dylib               0x38345c1d _pthread_body + 141
  2     libsystem_pthread.dylib               0x38345b8f _pthread_start + 103
  
  Thread: Unknown Name
  0     libsystem_kernel.dylib                0x382ddc7c __workq_kernreturn + 8
  
  Thread: Unknown Name
  0     libsystem_kernel.dylib                0x382ddc7c __workq_kernreturn + 8
  
  
  
  Crashed Registers
  _________________________________
  r12 0x148
  r10 0x190
  r11 0x1559ca80
  cpsr    0x10
  r4  0x6
  r5  0x3a15318c
  r6  0x0
  r7  0x27d45a60
  r0  0x0
  r1  0x0
  r2  0x0
  r3  0x2060
  sp  0x27d45a54
  r8  0x1558f8e0
  r9  0x1
  pc  0x382dd1fc
  lr  0x38346a33
  </code></pre>
  
  <p>The method crashing in SDWebImageCache.m is this:</p>
  
  <pre><code>- (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(void (^)(UIImage *image, SDImageCacheType cacheType))doneBlock
  {
      NSOperation *operation = NSOperation.new;
  
      if (!doneBlock) return nil;
  
      if (!key)
      {
          doneBlock(nil, SDImageCacheTypeNone);
          return nil;
      }
  
      // First check the in-memory cache...
      UIImage *image = [self imageFromMemoryCacheForKey:key];
      if (image)
      {
          doneBlock(image, SDImageCacheTypeMemory);
          return nil;
      }
  
      dispatch_async(self.ioQueue, ^
      {
          if (operation.isCancelled)
          {
              return;
          }
  
          @autoreleasepool
          {
              UIImage *diskImage = [self diskImageForKey:key];
              if (diskImage)
              {
                  CGFloat cost = diskImage.size.height * diskImage.size.width * diskImage.scale;
                  [self.memCache setObject:diskImage forKey:key cost:cost];
              }
  
              dispatch_main_sync_safe(^
              {
                  doneBlock(diskImage, SDImageCacheTypeDisk);
              });
          }
      });
  
      return operation;
  }
  </code></pre>
  
  <p>Has anyone experience this crash? If yes, is there a way to fix this?</p>
  
  <p>Line 308 where the crash occurs is this:</p>
  
  <pre><code>  dispatch_main_sync_safe(^
              {
                  doneBlock(diskImage, SDImageCacheTypeDisk);
              });
  </code></pre>
  
  <p>This method is called in another class from this method:</p>
  
  <pre><code>- (id&lt;SDWebImageOperation&gt;)downloadWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedWithFinishedBlock)completedBlock
  {    
      // Invoking this method without a completedBlock is pointless
      NSParameterAssert(completedBlock);
  
      // Very common mistake is to send the URL using NSString object instead of NSURL. For some strange reason, XCode won't
      // throw any warning for this type mismatch. Here we failsafe this error by allowing URLs to be passed as NSString.
      if ([url isKindOfClass:NSString.class])
      {
          url = [NSURL URLWithString:(NSString *)url];
      }
  
      // Prevents app crashing on argument type error like sending NSNull instead of NSURL
      if (![url isKindOfClass:NSURL.class])
      {
          url = nil;
      }
  
      __block SDWebImageCombinedOperation *operation = SDWebImageCombinedOperation.new;
      __weak SDWebImageCombinedOperation *weakOperation = operation;
  
      BOOL isFailedUrl = NO;
      @synchronized(self.failedURLs)
      {
          isFailedUrl = [self.failedURLs containsObject:url];
      }
  
      if (!url || (!(options &amp; SDWebImageRetryFailed) &amp;&amp; isFailedUrl))
      {
          dispatch_main_sync_safe(^
          {
                  NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist userInfo:nil];
                  completedBlock(nil, error, SDImageCacheTypeNone, YES);
          });
          return operation;
      }
  
      @synchronized(self.runningOperations)
      {
          [self.runningOperations addObject:operation];
      }
      NSString *key = [self cacheKeyForURL:url];
  
      operation.cacheOperation = [self.imageCache queryDiskCacheForKey:key done:^(UIImage *image, SDImageCacheType cacheType)
      {
          if (operation.isCancelled)
          {
              @synchronized(self.runningOperations)
              {
                  [self.runningOperations removeObject:operation];
              }
  
              return;
          }
  
          if ((!image || options &amp; SDWebImageRefreshCached) &amp;&amp; (![self.delegate respondsToSelector:@selector(imageManager:shouldDownloadImageForURL:)] || [self.delegate imageManager:self shouldDownloadImageForURL:url]))
          {
              if (image &amp;&amp; options &amp; SDWebImageRefreshCached)
              {
                  dispatch_main_sync_safe(^
                  {
                      // If image was found in the cache bug SDWebImageRefreshCached is provided, notify about the cached image
                      // AND try to re-download it in order to let a chance to NSURLCache to refresh it from server.
                      completedBlock(image, nil, cacheType, YES);
                  });
              }
  
              // download if no image or requested to refresh anyway, and download allowed by delegate
              SDWebImageDownloaderOptions downloaderOptions = 0;
              if (options &amp; SDWebImageLowPriority) downloaderOptions |= SDWebImageDownloaderLowPriority;
              if (options &amp; SDWebImageProgressiveDownload) downloaderOptions |= SDWebImageDownloaderProgressiveDownload;
              if (options &amp; SDWebImageRefreshCached) downloaderOptions |= SDWebImageDownloaderUseNSURLCache;
              if (options &amp; SDWebImageContinueInBackground) downloaderOptions |= SDWebImageDownloaderContinueInBackground;
              if (options &amp; SDWebImageHandleCookies) downloaderOptions |= SDWebImageDownloaderHandleCookies;
              if (image &amp;&amp; options &amp; SDWebImageRefreshCached)
              {
                  // force progressive off if image already cached but forced refreshing
                  downloaderOptions &amp;= ~SDWebImageDownloaderProgressiveDownload;
                  // ignore image read from NSURLCache if image if cached but force refreshing
                  downloaderOptions |= SDWebImageDownloaderIgnoreCachedResponse;
              }
              id&lt;SDWebImageOperation&gt; subOperation = [self.imageDownloader downloadImageWithURL:url options:downloaderOptions progress:progressBlock completed:^(UIImage *downloadedImage, NSData *data, NSError *error, BOOL finished)
              {                
                  if (weakOperation.isCancelled)
                  {
                      dispatch_main_sync_safe(^
                      {
                          completedBlock(nil, nil, SDImageCacheTypeNone, finished);
                      });
                  }
                  else if (error)
                  {
                      dispatch_main_sync_safe(^
                      {
                          completedBlock(nil, error, SDImageCacheTypeNone, finished);
                      });
  
                      if (error.code != NSURLErrorNotConnectedToInternet)
                      {
                          @synchronized(self.failedURLs)
                          {
                              [self.failedURLs addObject:url];
                          }
                      }
                  }
                  else
                  {
                      BOOL cacheOnDisk = !(options &amp; SDWebImageCacheMemoryOnly);
  
                      if (options &amp; SDWebImageRefreshCached &amp;&amp; image &amp;&amp; !downloadedImage)
                      {
                          // Image refresh hit the NSURLCache cache, do not call the completion block
                      }
                      // NOTE: We don't call transformDownloadedImage delegate method on animated images as most transformation code would mangle it
                      else if (downloadedImage &amp;&amp; !downloadedImage.images &amp;&amp; [self.delegate respondsToSelector:@selector(imageManager:transformDownloadedImage:withURL:)])
                      {
                          dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^
                          {
                              UIImage *transformedImage = [self.delegate imageManager:self transformDownloadedImage:downloadedImage withURL:url];
  
                              dispatch_main_sync_safe(^
                              {
                                  completedBlock(transformedImage, nil, SDImageCacheTypeNone, finished);
                              });
  
                              if (transformedImage &amp;&amp; finished)
                              {
                                  NSData *dataToStore = [transformedImage isEqual:downloadedImage] ? data : nil;
                                  [self.imageCache storeImage:transformedImage imageData:dataToStore forKey:key toDisk:cacheOnDisk];
                              }
                          });
                      }
                      else
                      {
                          dispatch_main_sync_safe(^
                          {
                              completedBlock(downloadedImage, nil, SDImageCacheTypeNone, finished);
                          });
  
                          if (downloadedImage &amp;&amp; finished)
                          {
                              [self.imageCache storeImage:downloadedImage imageData:data forKey:key toDisk:cacheOnDisk];
                          }
                      }
                  }
  
                  if (finished)
                  {
                      @synchronized(self.runningOperations)
                      {
                          [self.runningOperations removeObject:operation];
                      }
                  }
              }];
              operation.cancelBlock = ^{[subOperation cancel];};
          }
          else if (image)
          {
              dispatch_main_sync_safe(^
              {
                  completedBlock(image, nil, cacheType, YES);
              });
              @synchronized(self.runningOperations)
              {
                  [self.runningOperations removeObject:operation];
              }
          }
          else
          {
              // Image not in cache and download disallowed by delegate
              dispatch_main_sync_safe(^
              {
                  completedBlock(nil, nil, SDImageCacheTypeNone, YES);
              });
              @synchronized(self.runningOperations)
              {
                  [self.runningOperations removeObject:operation];
              }
          }
      }];
  
      return operation;
  }
  </code></pre>