2016-11-02 6 views
28

NSURLSessionDataDelegate을 구현하고 작업을 시작하면 매우 가끔 EXC_BAD_ACCESS가 throw됩니다. 오류를 제공하는 실제 호출 방법은 다양하지만 항상 CFNetwork에서옵니다. 대부분 호출 메서드는 NSURLSession delegate_dataTask:didReceiveData:completionHandler에서옵니다. 아래에 다른 발신자가있는 두 개의 오류 로그를 첨부했습니다. 내 구현도 NSURLSessionDataDelegate에 첨부했습니다.NSURLSession이 EXC_BAD_ACCESS의 원인이 됨

안정적으로 오류를 재현 할 수 없으므로 공유 할 예제 스크립트가 없습니다. Downloader 개체를 만들고 시작하면 결국 오류가 발생합니다. 더 큰 파일을 사용하면 더 자주 발생하는 것 같습니다. 여기에 잘못된 것을 구현 했습니까? 이 stacktrace에서 디버깅하는 좋은 방법이 있습니까?

iOS10 및 10.1.1에서 동일한 결과를 테스트했습니다.

구현 :

class Downloader: NSObject, NSURLSessionDataDelegate { 
    private let url: String 
    var finished = false 
    let finishCondition = NSCondition() 

    init(url:String) { 
     self.url = url 
     super.init() 
    } 

    func start() { 
     let config = NSURLSessionConfiguration.defaultSessionConfiguration() 
     let session = NSURLSession(configuration: config, 
           delegate: self, 
           delegateQueue: nil) 
     guard let u = NSURL(string: url) else { 
      return 
     } 
     let request = NSMutableURLRequest(URL: u) 
     let task = session.dataTaskWithRequest(request) 
     task.resume() 
    } 

    func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, 
        didReceiveData data: NSData) { 
    } 

    func URLSession(session: NSURLSession, 
        task: NSURLSessionTask, 
        didCompleteWithError error: NSError?) { 
     session.invalidateAndCancel() 
    } 

    func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, 
        didReceiveResponse response: NSURLResponse, 
             completionHandler: (NSURLSessionResponseDisposition) -> Void) { 
     completionHandler(NSURLSessionResponseDisposition.Allow) 
    } 

    func waitForFinish() { 
     finishCondition.lock() 
     while !finished { 
      finishCondition.wait() 
     } 
     finishCondition.unlock() 
    } 

    func URLSession(session: NSURLSession, didBecomeInvalidWithError error: NSError?) { 
     finishCondition.lock() 
     finished = true 
     finishCondition.broadcast() 
     finishCondition.unlock() 
    } 
} 

충돌 로그 # 1 :

* thread #5: tid = 0x25923, 0x0000000100042e8c libBacktraceRecording.dylib`__gcd_queue_item_enqueue_hook_block_invoke, queue = 'com.apple.NSURLSession-work', stop reason = EXC_BAD_ACCESS (code=1, address=0xf8686a68b98c6ec8) 
    * frame #0: 0x0000000100042e8c libBacktraceRecording.dylib`__gcd_queue_item_enqueue_hook_block_invoke 
    frame #1: 0x000000010004241c libBacktraceRecording.dylib`gcd_queue_item_enqueue_hook + 232 
    frame #2: 0x000000010065dee8 libdispatch.dylib`_dispatch_introspection_queue_item_enqueue_hook + 40 
    frame #3: 0x000000010063cba4 libdispatch.dylib`_dispatch_queue_push + 196 
    frame #4: 0x000000018ba50500 Foundation`iop_promote_qos_outward + 112 
    frame #5: 0x000000018ba4e524 Foundation`-[NSOperation setQualityOfService:] + 168 
    frame #6: 0x000000018b9d7714 Foundation`-[NSOperationQueue addOperationWithBlock:] + 76 
    frame #7: 0x000000018b73f82c CFNetwork`-[NSURLSession delegate_dataTask:didReceiveData:completionHandler:] + 208 
    frame #8: 0x000000018b5a2c5c CFNetwork`-[__NSCFLocalSessionTask _task_onqueue_didReceiveDispatchData:completionHandler:] + 276 
    frame #9: 0x000000018b5a5474 CFNetwork`-[__NSCFLocalSessionTask connection:didReceiveData:completion:] + 164 
    frame #10: 0x000000018b647bf0 CFNetwork`__48-[__NSCFURLLocalSessionConnection _tick_running]_block_invoke + 120 
    frame #11: 0x000000018b647b60 CFNetwork`-[__NSCFURLLocalSessionConnection _tick_running] + 344 
    frame #12: 0x000000018b648c74 CFNetwork`-[__NSCFURLLocalSessionConnection _didReceiveData:] + 412 
    frame #13: 0x000000018b64af8c CFNetwork`SessionConnectionLoadable::_loaderClientEvent_DidReceiveData(__CFArray const*) + 52 
    frame #14: 0x000000018b6f823c CFNetwork`___ZN19URLConnectionLoader19protocolDidLoadDataEPK8__CFDatax_block_invoke_2 + 44 
    frame #15: 0x000000018b64b58c CFNetwork`___ZN25SessionConnectionLoadable21withLoaderClientAsyncEU13block_pointerFvP21LoaderClientInterfaceE_block_invoke + 32 
    frame #16: 0x000000010063125c libdispatch.dylib`_dispatch_call_block_and_release + 24 
    frame #17: 0x000000010063121c libdispatch.dylib`_dispatch_client_callout + 16 
    frame #18: 0x000000010063eb54 libdispatch.dylib`_dispatch_queue_serial_drain + 1136 
    frame #19: 0x0000000100634ce4 libdispatch.dylib`_dispatch_queue_invoke + 672 
    frame #20: 0x0000000100640e6c libdispatch.dylib`_dispatch_root_queue_drain + 584 
    frame #21: 0x0000000100640bb8 libdispatch.dylib`_dispatch_worker_thread3 + 140 
    frame #22: 0x000000018a01e2b8 libsystem_pthread.dylib`_pthread_wqthread + 1288 
    frame #23: 0x000000018a01dda4 libsystem_pthread.dylib`start_wqthread + 4 

충돌 로그 # 2 :

* thread #12: tid = 0x2521f, 0x000000010010ae8c libBacktraceRecording.dylib`__gcd_queue_item_enqueue_hook_block_invoke, queue = 'com.apple.CFNetwork.Connection', stop reason = EXC_BAD_ACCESS (code=1, address=0xd00f524835000200) 
     * frame #0: 0x000000010010ae8c libBacktraceRecording.dylib`__gcd_queue_item_enqueue_hook_block_invoke 
     frame #1: 0x000000010010a41c libBacktraceRecording.dylib`gcd_queue_item_enqueue_hook + 232 
     frame #2: 0x0000000100759ee8 libdispatch.dylib`_dispatch_introspection_queue_item_enqueue_hook + 40 
     frame #3: 0x0000000100738ba4 libdispatch.dylib`_dispatch_queue_push + 196 
     frame #4: 0x00000001975ccb3c libnetwork.dylib`nw_connection_read + 448 
     frame #5: 0x00000001975d938c libnetwork.dylib`tcp_connection_read + 168 
     frame #6: 0x000000018b719d54 CFNetwork`TCPIOConnection::read(unsigned long, unsigned long, void (dispatch_data_s*, CFStreamError) block_pointer) + 172 
     frame #7: 0x000000018b782af4 CFNetwork`HTTPEngine::_getBodyIntelligently(void (dispatch_data_s*, CFStreamError, bool) block_pointer) + 816 
     frame #8: 0x000000018b780d0c CFNetwork`HTTPEngine::_readBodyStartNextRead() + 76 
     frame #9: 0x000000018b783664 CFNetwork`___ZN10HTTPEngine21_getBodyIntelligentlyEU13block_pointerFvP15dispatch_data_s13CFStreamErrorbE_block_invoke.56 + 344 
     frame #10: 0x000000018b719f64 CFNetwork`___ZN15TCPIOConnection4readEmmU13block_pointerFvP15dispatch_data_s13CFStreamErrorE_block_invoke + 480 
     frame #11: 0x000000010072d25c libdispatch.dylib`_dispatch_call_block_and_release + 24 
     frame #12: 0x000000010072d21c libdispatch.dylib`_dispatch_client_callout + 16 
     frame #13: 0x000000010073ab54 libdispatch.dylib`_dispatch_queue_serial_drain + 1136 
     frame #14: 0x0000000100730ce4 libdispatch.dylib`_dispatch_queue_invoke + 672 
     frame #15: 0x000000010073ce6c libdispatch.dylib`_dispatch_root_queue_drain + 584 
     frame #16: 0x000000010073cbb8 libdispatch.dylib`_dispatch_worker_thread3 + 140 
     frame #17: 0x000000018a01e2b8 libsystem_pthread.dylib`_pthread_wqthread + 1288 
     frame #18: 0x000000018a01dda4 libsystem_pthread.dylib`start_wqthread + 4 

UPDATE : 지금 반 안정적하여이 오류를 재현 할 수 있습니다 iOS 시뮬레이터에서 아래에 루프를 붙여 넣기를 실행합니다. 이것은 iOS 9.3에서는 발생하지 않습니다. 아래 코드를 실행하면 1 분 이내에 오류가 발생합니다. 장치와 비교할 때 시뮬레이터에서 발생할 가능성이 매우 높기 때문에 더 많은 처리 능력/코어로 인해 동시성 문제가 발생할 것으로 생각합니다. 오류를 재현하려면 다음을 실행합니다

var i = 0 
while true { 
    print("running: \(i)") 
    // random url, larger files seem more likely to cause error 
    let url = "http://qthttp.apple.com.edgesuite.net/1010qwoeiuryfg/3340/33409.ts" 
    let c = Downloader(url: url) 
    c.start() 
    c.waitForFinish() 
    i += 1 
} 
+2

iOS 10에서는 보이지만 9.3 시뮬레이터에서는 그렇지 않습니다. 같은 증상, 같은 역 추적, 단서 없음. – Icydog

+2

10.0 시뮬레이터에서 비슷한 오류가 발생합니다.'''thread # 64 : tid = 0x5e3688, 0x000000010717deac libbacktraceRecording.dylib'__gcd_queue_item_enqueue_hook_block_invoke + 4, queue = 'com.apple.network.connections', 중지 이유 = EXC_BAD_ACCESS (코드 = EXC_I386_GPFLT)''' – yuf

+1

나는 유일하게 기쁘다. 이것을 디버깅하는 좋은 방법이 있습니까? – oliveroneill

답변

43

Apple 기술 지원부에서 Xcode 내에서 디버깅하는 데 사용되는 libBacktraceRecording.dylib 라이브러리의 버그임을 확인한 후이를 확인했습니다. 나는 버그 보고서를 제출했으며 사용자 장치에 충돌하지 않을 것이라고 말했는데, 이는 대부분의 사용자 장치에없는 라이브러리 내에서 발생하는 디버그 오류이기 때문입니다.

+1

버그 보고서에 대한 링크 또는 자세한 정보를 공유 할 수 있습니까? 그래서 다른 사람들은 진전을 볼 수 있습니까? Apple 기술 지원팀과 정확히 어떻게 연락 했습니까? 그들은 반응합니까? – Honey

+1

아직 openradar에 올려 놓지는 않았지만, Apple은 일반적으로 어쨌든 진행 상황에 대한 피드백을 거의 제공하지 않습니다.https://developer.apple.com/support/technical/을 통해 Apple에 개발자 기술 지원을 요청할 수 있습니다. 그들은 보통 다음 영업일에 응답 했으므로 반응이 좋았습니다. – oliveroneill

+2

시에라의 Mac에서 똑같은 충돌이 발생합니다. 같은 증상, (EXC_BAD_ACCESS는 NSURLConnectionLoader 코드 깊이이지만 Xcode 디버그 세션에서만 발생); 모든 가솔린 Malloc, 주소 sanitizer 등은 모두 그것을 고칠 수 있습니다. 동일한 dylib가 Mac에서 사용되었습니다 – mackworth

1

가 좀비 악기에서 실행 해보십시오. 내 생각 엔 NSURLSession이 작동하는 동안 Downloader 클래스 인스턴스가 할당 해제되는 것입니다. 따라서 didReceiveData 메소드를 호출 할 때 이전에 객체에 의해 점유 된 메모리에 다른 내용이 포함되어있을 것입니다. (그게 좀비입니다.)

+2

좀비 악기 내에서 오류를 다시 만들 수 없습니다. 그러나 "좀비 객체"를 "Edit Scheme"에서 켜면 좀비 객체 경고를 출력하지 않고 동일한 오류가 발생합니다. 이 둘의 차이점은 무엇입니까? – oliveroneill

+1

나는 비슷한 사고가 일어나고 있었는데, 일어 났을 때 좀비가 있었지만 아무 것도 잡지 못했습니다. – yuf

+0

이 문제는 Sierra 10.12.5의 Xcode 9, Beta 5에서 여전히 발생합니다. – manmal

관련 문제