2013-11-26 53 views
1

的我得到这个崩溃日志(从用户得到它,不能复制):SIGABRT崩溃,因为SDWebImageCache

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 

在SDWebImageCache.m崩溃的方法是这样的:

- (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; 
} 

有任何人都会遇到这个崩溃如果是的话,有没有办法解决这个问题?

线308在碰撞发生是这样的:

dispatch_main_sync_safe(^ 
      { 
       doneBlock(diskImage, SDImageCacheTypeDisk); 
      }); 

这种方法在其他类中调用此方法:

- (id<SDWebImageOperation>)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 & SDWebImageRetryFailed) && 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 & SDWebImageRefreshCached) && (![self.delegate respondsToSelector:@selector(imageManager:shouldDownloadImageForURL:)] || [self.delegate imageManager:self shouldDownloadImageForURL:url])) 
     { 
      if (image && options & 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 & SDWebImageLowPriority) downloaderOptions |= SDWebImageDownloaderLowPriority; 
      if (options & SDWebImageProgressiveDownload) downloaderOptions |= SDWebImageDownloaderProgressiveDownload; 
      if (options & SDWebImageRefreshCached) downloaderOptions |= SDWebImageDownloaderUseNSURLCache; 
      if (options & SDWebImageContinueInBackground) downloaderOptions |= SDWebImageDownloaderContinueInBackground; 
      if (options & SDWebImageHandleCookies) downloaderOptions |= SDWebImageDownloaderHandleCookies; 
      if (image && options & SDWebImageRefreshCached) 
      { 
       // force progressive off if image already cached but forced refreshing 
       downloaderOptions &= ~SDWebImageDownloaderProgressiveDownload; 
       // ignore image read from NSURLCache if image if cached but force refreshing 
       downloaderOptions |= SDWebImageDownloaderIgnoreCachedResponse; 
      } 
      id<SDWebImageOperation> 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 & SDWebImageCacheMemoryOnly); 

        if (options & SDWebImageRefreshCached && image && !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 && !downloadedImage.images && [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 && 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 && 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; 
} 
+0

在其中一线发生崩溃。 –

+0

这里:'dispatch_main_sync_safe(^ { doneBlock(diskImage,SDImageCacheTypeDisk); });' –

+0

捕获异常,引发异常,这将帮助您找出问题所在。 – Emmanuel

回答

1

正如报告中说,这是关系到信号量。我发现有问题的行,你评论

enterdispatch_main_sync_safe(^ { doneBlock(diskImage, SDImageCacheTypeDisk); }); 

是正是被报道SDWebImage GitHub的错误报告[1]造成僵局的一个。如果我理解正确,这个问题已经解决,最新的补丁提交是2个小时前。

也许你可以在未来的版本,或者您可以使用git,它就在那里..

我来源:

[1] https://github.com/rs/SDWebImage/issues/507

+0

很高兴看到周围有修复。我在github上修复之前就开始了这个线程。非常感谢您的回复。 –

相关问题