2015-08-11 4 views
3

Я уверен, что это нечто глупое, что я делаю, но через час я не вижу его. Может быть, ты сможешь. Редактировать: это устройство (iPhone 5S w/iOS 8.4), а не симулятор.AFNetworking deadlock on tasks (tasksForKeyPath)

У меня есть приложение iOS 8 с DownloadManager, singleton, который подклассифицирует AFHTTPSessionManager, используя BackgroundSession. Он работал хорошо, но теперь я сделал что-то и получается, что AFNetworking тупики в setDownloadTaskDidFinishDownloadingBlock, когда я ссылаться на self.tasks.count:

[self setDownloadTaskDidFinishDownloadingBlock:^NSURL *(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location) { 
    // POINT OF THIS BLOCK: RETURNS A FILENAME URL WHERE THE DOWNLOAD SHOULD GET STORED 
    __strong typeof(self) strongSelf = weakS; 
    if(!strongSelf) 
     return nil; 

    // deadlocks here on tasks.count 
    DDLogVerbose(@"setDownloadTaskDidFinishDownloadingBlock, start; dataTasks - %lu, downloadTasks - %lu", (unsigned long)strongSelf.dataTaskManager.tasks.count, (unsigned long)strongSelf.tasks.count); 

dataTaskManager относится к отдельно наследнике AFHTTPSessionManager который является стандартной сессии (не фон) - удаление этого из строки регистрации выше не решает проблему.

completionQueue DownloadManager имеет значение в инициализации будет теми же серийные очереди, который использует DownloadManager для всего:

_processingQueue = dispatch_queue_create([[BUNDLE_IDENTIFIER stringByAppendingString:@".BackgroundSessionManager"] cStringUsingEncoding:NSUTF8StringEncoding], NULL); 
    dispatch_queue_set_specific(_processingQueue, (__bridge const void *)(_processingQueue), (__bridge void *)(_processingQueue), NULL); 
    self.completionQueue = _processingQueue; // set AFNetworking completionQueue to be our queue 

... но это, кажется, не поможет.

Вот тупиковый:

My threads, let me show them to you

(lldb) bt all 
    thread #1: tid = 0x137b14, 0x0000000198958e0c libsystem_kernel.dylib`mach_msg_trap + 8, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP 
    frame #0: 0x0000000198958e0c libsystem_kernel.dylib`mach_msg_trap + 8 
    frame #1: 0x0000000198958c88 libsystem_kernel.dylib`mach_msg + 72 
    frame #2: 0x00000001864eb724 CoreFoundation`__CFRunLoopServiceMachPort + 200 
    frame #3: 0x00000001864e9678 CoreFoundation`__CFRunLoopRun + 940 
    frame #4: 0x00000001864152d4 CoreFoundation`CFRunLoopRunSpecific + 396 
    frame #5: 0x000000018fe736fc GraphicsServices`GSEventRunModal + 168 
    frame #6: 0x000000018b012f40 UIKit`UIApplicationMain + 1488 
    frame #7: 0x00000001000a60a4 Grab`main(argc=1, argv=0x000000016fd8ba80) + 124 at main.m:14 
    frame #8: 0x000000019885aa08 libdyld.dylib`start + 4 

    thread #2: tid = 0x137b6b, 0x0000000198958c24 libsystem_kernel.dylib`kevent64 + 8, queue = 'com.apple.libdispatch-manager' 
    frame #0: 0x0000000198958c24 libsystem_kernel.dylib`kevent64 + 8 
    frame #1: 0x0000000100496588 libdispatch.dylib`_dispatch_mgr_invoke + 276 
    frame #2: 0x000000010048709c libdispatch.dylib`_dispatch_mgr_thread + 52 

    thread #3: tid = 0x137b6c, 0x0000000198973c78 libsystem_kernel.dylib`__workq_kernreturn + 8 
    frame #0: 0x0000000198973c78 libsystem_kernel.dylib`__workq_kernreturn + 8 
    frame #1: 0x0000000198a0d2dc libsystem_pthread.dylib`_pthread_wqthread + 992 

    thread #6: tid = 0x137b6f, 0x0000000198973c78 libsystem_kernel.dylib`__workq_kernreturn + 8 
    frame #0: 0x0000000198973c78 libsystem_kernel.dylib`__workq_kernreturn + 8 
    frame #1: 0x0000000198a0d2dc libsystem_pthread.dylib`_pthread_wqthread + 992 

* thread #7: tid = 0x137b97, 0x0000000198958e48 libsystem_kernel.dylib`semaphore_wait_trap + 8, queue = 'NSOperationQueue 0x17022f180 :: NSOperation 0x170449cf0 (QOS: LEGACY)' 
    frame #0: 0x0000000198958e48 libsystem_kernel.dylib`semaphore_wait_trap + 8 
    frame #1: 0x0000000100494544 libdispatch.dylib`_dispatch_semaphore_wait_slow + 256 
    * frame #2: 0x000000010018e8f4 Grab`-[AFURLSessionManager tasksForKeyPath:](self=0x0000000127d1e050, _cmd=0x0000000100203d49, keyPath=0x000000017042fdc0) + 340 at AFURLSessionManager.m:617 
    frame #3: 0x000000010018ee88 Grab`-[AFURLSessionManager tasks](self=0x0000000127d1e050, _cmd=0x0000000191f79785) + 76 at AFURLSessionManager.m:623 
    frame #4: 0x00000001000a8efc Grab`__36-[DownloadManager loadSessionBlocks]_block_invoke150(.block_descriptor=<unavailable>, session=0x0000000170132700, downloadTask=0x0000000127e408b0, location=0x00000001702bf860) + 328 at DownloadManager.m:149 
    frame #5: 0x0000000100193734 Grab`-[AFURLSessionManager URLSession:downloadTask:didFinishDownloadingToURL:](self=0x0000000127d1e050, _cmd=0x000000018d2b4ddd, session=0x0000000170132700, downloadTask=0x0000000127e408b0, location=0x00000001702bf860) + 292 at AFURLSessionManager.m:1082 
    frame #6: 0x0000000185f70b70 CFNetwork`__82-[NSURLSession delegate_downloadTask:didFinishDownloadingToURL:completionHandler:]_block_invoke + 40 
    frame #7: 0x000000018741b1c4 Foundation`__NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 16 
    frame #8: 0x000000018736c604 Foundation`-[NSBlockOperation main] + 96 
    frame #9: 0x000000018735c1cc Foundation`-[__NSOperationInternal _start:] + 636 
    frame #10: 0x000000018741df28 Foundation`__NSOQSchedule_f + 228 
    frame #11: 0x0000000100484f94 libdispatch.dylib`_dispatch_client_callout + 16 
    frame #12: 0x000000010048fdb8 libdispatch.dylib`_dispatch_queue_drain + 780 
    frame #13: 0x00000001004882c4 libdispatch.dylib`_dispatch_queue_invoke + 132 
    frame #14: 0x00000001004925d4 libdispatch.dylib`_dispatch_root_queue_drain + 772 
    frame #15: 0x0000000100494248 libdispatch.dylib`_dispatch_worker_thread3 + 132 
    frame #16: 0x0000000198a0d22c libsystem_pthread.dylib`_pthread_wqthread + 816 

    thread #12: tid = 0x137b9e, 0x0000000198973c78 libsystem_kernel.dylib`__workq_kernreturn + 8 
    frame #0: 0x0000000198973c78 libsystem_kernel.dylib`__workq_kernreturn + 8 
    frame #1: 0x0000000198a0d2dc libsystem_pthread.dylib`_pthread_wqthread + 992 

    thread #10: tid = 0x137bf9, 0x0000000198958e0c libsystem_kernel.dylib`mach_msg_trap + 8, name = 'com.apple.NSURLConnectionLoader' 
    frame #0: 0x0000000198958e0c libsystem_kernel.dylib`mach_msg_trap + 8 
    frame #1: 0x0000000198958c88 libsystem_kernel.dylib`mach_msg + 72 
    frame #2: 0x00000001864eb724 CoreFoundation`__CFRunLoopServiceMachPort + 200 
    frame #3: 0x00000001864e9678 CoreFoundation`__CFRunLoopRun + 940 
    frame #4: 0x00000001864152d4 CoreFoundation`CFRunLoopRunSpecific + 396 
    frame #5: 0x0000000185ef2594 CFNetwork`+[NSURLConnection(Loader) _resourceLoadLoop:] + 440 
    frame #6: 0x0000000187435db8 Foundation`__NSThread__main__ + 1072 
    frame #7: 0x0000000198a0fdc8 libsystem_pthread.dylib`_pthread_body + 164 
    frame #8: 0x0000000198a0fd24 libsystem_pthread.dylib`_pthread_start + 160 

    thread #11: tid = 0x137bfa, 0x0000000198973498 libsystem_kernel.dylib`__select + 8, name = 'com.apple.CFSocket.private' 
    frame #0: 0x0000000198973498 libsystem_kernel.dylib`__select + 8 
    frame #1: 0x00000001864f1128 CoreFoundation`__CFSocketManager + 672 
    frame #2: 0x0000000198a0fdc8 libsystem_pthread.dylib`_pthread_body + 164 
    frame #3: 0x0000000198a0fd24 libsystem_pthread.dylib`_pthread_start + 160 
(lldb) 

ответ

1

.... Я понял это. Из-за того, что реализовано taskForKeyPath, невозможно вызвать. * Задачи из таких блоков, как setTaskDidCompleteBlock, потому что метод NSURLSession под ним (getTasksWithCompletionHandler) перезвонит в очередь делегатов, который, конечно, заблокирован исходным блоком, например setTaskDidCompleteBlock. Это отстой, но это своего рода вина Apple, я думаю, для создания метода, который получает задачи асинхронные ...

Так что обходной путь, чтобы избежать текущих задач из блоков, как setTaskDidCompleteBlock (или что-нибудь, что они называют)