2016-11-02 30 views
28

NSURLSessionDataDelegate uygulanmasının ve bir görevin başlatılmasının çok zaman zaman bir EXC_BAD_ACCESS atayacağını fark ettim. Hatayı veren gerçek çağrı yöntemi değişebilir, ancak her zaman CFNetwork'dan gelir. Çoğunlukla, arama yöntemi NSURLSession delegate_dataTask:didReceiveData:completionHandler'dan gelir. Aşağıda farklı arayanlarla iki kilitlenme kaydı ekledim. Ayrıca, NSURLSessionDataDelegate uygulamasını ekledim.NSURLSession neden EXC_BAD_ACCESS

Maalesef bu hatayı güvenli bir şekilde yeniden oluşturamıyorum, dolayısıyla paylaşmak için bir örnek komut dosyası yok. Downloader nesnelerinin oluşturulması ve başlatılması, sonunda hata oluşturacaktır. Daha büyük dosyalarla daha sık gerçekleşiyor gibi görünüyor. Burada yanlış bir şey mi uyguladım? Bu stacktrace'den hata ayıklamanın iyi bir yolu var mı?

iOS10 ve 10.1.1 üzerinde aynı sonuçları test ettik.

Uygulama:

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

Kilitlenme günlük # 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 

Kilitlenme günlük # 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 

GÜNCELLEME: Şimdi yarı güvenilir tarafından bu hatayı üretebilir iOS Simulator'da aşağıdakini yapıştırılmış döngü çalıştırabilirsiniz. Bu iOS 9.3'te gerçekleşmez. Aşağıdaki kodu çalıştırırsanız, bir dakika içinde hatayı almanız gerekir. Bir cihazla karşılaştırıldığında simülatörde meydana gelme olasılığı yüksek olduğu için, daha fazla işlemci gücü/çekirdeği ile daha olası hale gelen bir eşzamanlılık sorunu olduğunu varsayabilirim. Hata yeniden oluşturmak için bu çalıştırın:

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

Bunu iOS 10'da değil, 9.3 simülatöründe de görüyoruz. Aynı belirtiler, aynı backtrace, ipucu yok. – Icydog

+2

10.0 simülatöründe benzer bir çökme görüyorum '' '* thread # 64: tid = 0x5e3688, 0x000000010717deac libBacktraceRecording.dylib'__gcd_queue_item_enqueue_hook_block_invoke + 4, queue = 'com.apple.network.connections', durma nedeni = EXC_BAD_ACCESS (kod = EXC_I386_GPFLT) '' – yuf

+1

Sadece bir tane olmadığına sevindim. Bunu hata ayıklamanın iyi bir yolu var mı? – oliveroneill

cevap

43

Apple Teknik Destek ile konuştuktan sonra, Xcode içinde hata ayıklamak için kullanılan libBacktraceRecording.dylib kitaplığındaki bir hata olduğunu onayladık. Bir hata raporu hazırladım ve bir kullanıcı cihazında kilitlenmeyeceği söylendi. Çünkü bu, çoğu kullanıcının cihazında bulunmayan bir kütüphanede gerçekleşen bir hata ayıklama hatasıdır.

+1

Hata raporu hakkında bir bağlantı veya daha fazla bilgi paylaşabilir misiniz? Diğerleri ilerlemesini görebilir mi? Ve Apple Teknik desteğiyle tam olarak nasıl iletişime geçtiniz? Onlar duyarlı mı? – Honey

+1

Ben henüz openradar'a koymadım, ancak Apple zaten ilerleme konusunda çok az geri bildirim veriyor.Geliştirici teknik desteği için Apple ile https://developer.apple.com/support/technical/ adresinden iletişime geçebilirsiniz. Genellikle bir sonraki iş günü tarafından cevap verdi, çok duyarlı. – oliveroneill

+2

Sierra’daki Mac’te tam olarak aynı çökmeyi elde ediyorum; Aynı belirtiler, (NSURLConnectionLoader kodunda EXC_BAD_ACCESS, ancak yalnızca Xcode hata ayıklama oturumlarından); Malloc, adres dezenfektanı, vb. Aynı dylib Mac – mackworth

1

Zombiler Instrument'da çalıştırmayı deneyin. Benim tahminim, Downloader sınıf örneğinizin NSURLSession çalışırken serbest bırakılmasıdır, bu yüzden didReceiveData yöntemini çağırmaya gittiğinde, eskiden nesneniz tarafından işgal edilen bellek başka bir şey içerir. (Bu bir zombidir.)

+2

Zombi Enstrümanı içindeki hatayı yeniden oluşturamadım. Ancak "Şema Düzenleme" den "Zombie Nesneleri" ni açmak, herhangi bir zombi nesnesi uyarısı vermeden aynı hatayı vermiştir. Bu ikisi arasında bir fark var mı? – oliveroneill

+1

Benzer bir çökme görüyorum ve ne zaman olduysa zombiler yaptım, ama hiçbir şey yakalamadı. – yuf

+0

Bunun hala, Sierra 10.12.5'teki Xcode 9, beta 5'ten itibaren gerçekleştiğini onaylayabilirim. – manmal