iOS: la debugging de misterioso CFNetwork <networkingacted> se bloquea en com.apple.NSURLConnectionLoader durante la búsqueda de background

He comenzado a ver este locking en algunos dispositivos en producción. La información proporcionada por Fabric Crashlytics y iOS es muy limitada en este caso y no estoy seguro de cómo depurarlo.

Lo único común para los lockings es que sucedió en iPhone 5S / iOS 10.2.1, pero eso podría ser solo una coincidencia.

Lo que vale la pena mencionar es que estoy usando Alamofire (4.3.0) donde un problema similar ya debería haber sido reparado.

Crashlog:

 EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x0000000000000020 Crashed: com.apple.NSURLConnectionLoader 0 libobjc.A.dylib 0x189c400a0 objc_retain + 16 1 CFNetwork 0x18b92d1d4 <networkingacted> + 240 2 CFNetwork 0x18b888e68 <networkingacted> + 348 3 CFNetwork 0x18b95dc80 <networkingacted> + 104 4 CFNetwork 0x18b95dc0c <networkingacted> + 36 5 CFNetwork 0x18b8f32ac <networkingacted> + 332 6 CFNetwork 0x18b8f3120 <networkingacted> + 60 7 CFNetwork 0x18b8f30b8 <networkingacted> + 268 8 CFNetwork 0x18b865040 <networkingacted> + 116 9 CFNetwork 0x18b7f7290 <networkingacted> + 48 10 CFNetwork 0x18b7f71c4 <networkingacted> + 220 11 CFNetwork 0x18b7f5550 <networkingacted> + 128 12 CFNetwork 0x18b92ca7c <networkingacted> + 1904 13 CFNetwork 0x18b92c23c <networkingacted> + 144 14 CFNetwork 0x18b92e18c <networkingacted> + 28 15 libdispatch.dylib 0x18a07a1bc _dispatch_client_callout + 16 16 libdispatch.dylib 0x18a085ab0 _dispatch_block_invoke_direct + 376 17 CFNetwork 0x18ba2a598 <networkingacted> + 36 18 CoreFoundation 0x18b0c9c18 CFArrayApplyFunction + 68 19 CFNetwork 0x18ba2a47c <networkingacted> + 136 20 CFNetwork 0x18ba2b7a4 <networkingacted> + 312 21 CFNetwork 0x18ba2b510 <networkingacted> + 64 22 CoreFoundation 0x18b19eb5c __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24 23 CoreFoundation 0x18b19e4a4 __CFRunLoopDoSources0 + 524 24 CoreFoundation 0x18b19c0a4 __CFRunLoopRun + 804 25 CoreFoundation 0x18b0ca2b8 CFRunLoopRunSpecific + 444 26 CFNetwork 0x18b8cfa70 <networkingacted> + 336 27 Foundation 0x18bd04e68 __NSThread__start__ + 1024 28 libsystem_pthread.dylib 0x18a285850 <networkingacted> + 240 29 libsystem_pthread.dylib 0x18a285760 _pthread_start + 282 30 libsystem_pthread.dylib 0x18a282d94 thread_start + 4 

Actualizar:

Después de agregar un logging adicional, he descubierto que el locking está sucediendo durante la actualización de la aplicación en segundo plano . De acuerdo con la documentation, "la aplicación tiene hasta 30 segundos de time de reloj de panetworking para realizar la operación de descarga y llamar al bloque de manejador de finalización especificado".

Sin embargo, puedo ver en los loggings que el locking se produce al mismo time (el mismo segundo, no puedo ver los milisegundos en los loggings de locking) cuando se dispara la request. En otras palabras, casi no hay time entre las func application(_ application:, performFetchWithCompletionHandler: sistema func application(_ application:, performFetchWithCompletionHandler: y el locking.

Por lo tanto, este no debería ser el caso cuando el sistema mata a la aplicación por pasar demasiado time en la ejecución de background.

Esto no tiene nada que ver con AlamoFire. La stack de NSURLSession y NSURLConnection son increíblemente complejas y están escritas en C basadas en CoreFoundation, lo que significa que tampoco obtienen los beneficios de ARC. Lo más probable es que se trate de un error sutil de subprocesss múltiples en algún lugar profundo de la stack que solo ocurra en ciertas circunstancias, y probablemente sea altamente dependiente del time.

En este caso particular, un object se ha completado (probablemente por una reference débil a cero en alguna parte) y alguna parte de la stack CF todavía lo está utilizando, e intenta desreferencer el object para retenerlo usando API de nivel C, lo que resulta en un Derivación de puntero NULL.

Más específicamente, es probable que vea este locking: https://github.com/PhilipsHue/PhilipsHueSDK-iOS-OSX/issues/52

En cuanto a evitarlo, es poco probable que tenga éxito. Su mejor opción es asegurarse de que su aplicación guarde correctamente el estado y reinicie lo más rápido posible de un arranque en frío para que la diferencia entre un arranque en frío y un arranque en caliente no tenga importancia.

Dicho esto, una cosa que puede intentar es cancelar todas las conexiones destacadas pendientes tan pronto como reciba una notificación de que va a un segundo plano, y luego reiniciarlas en una session con configuration discretionary en SÍ.