3

I've written an app in Swift which crashes on the following lines, when in Low Power Mode. It's basically a request that runs on a background thread. And some UI updates that's happening on the main thread.

I can't recreate the crash on my phone when in Low Power Mode, but according to my users this is the root cause.

// Run the request on a background thread
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
   self.runRequestOnBackgroundThread(request)
});

func runRequestOnBackgroundThread(request: NSMutableURLRequest) {
    //We need to update the UI on the mainthread/ ONLY THE UI
    dispatch_async(dispatch_get_main_queue(), {
        self.scanInProgress()
    })
    let session = NSURLSession.sharedSession()
    // run the request
    let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
        self.analyzeResults(data!)
    })
    task.resume()
}


func analyzeResults(dataToParse: NSData) {
    // Update UI on the main thread and analyze data from request
    // Line 491 below this line
    dispatch_async(dispatch_get_main_queue(), {
        //Here goes some regex
    })

I also found this on Apple.com:

Users who wish to prolong their iPhone’s battery life can enable Low Power Mode under Settings > Battery. In Low Power Mode, iOS conserves battery life by enacting certain energy-saving measures. For example, the system may:

  • Reduce CPU and GPU performance
  • Pause discretionary and background activities, including networking
  • Reduce screen brightness
  • Reduce the timeout for auto-locking the device
  • Disable Mail fetch
  • Disable motion effects
  • Disable animated wallpapers

Sound like the problem is with Pause discretionary and background activities, including networking?

How can I make the request in the background and update the UI on the mainthread meanwhile when Low Power Mode is enabled (I have some UIView.animateWithDuration going)? The user will always have the app in the foreground when these methods are run, does this mean I should run the request on the main thread?

Below is the Crash report from Fabric/Crashlytics:

#-1. com.apple.main-thread
0  libsystem_platform.dylib       0x18428d8b0 _platform_memcmp + 32
1  CoreFoundation                 0x1845fe710 __CFStringEqual + 256
2  CoreFoundation                 0x1845fe710 __CFStringEqual + 256
3  CoreFoundation                 0x18450ebf4 CFEqual + 400
4  CoreFoundation                 0x184670314 __NSCacheKeyEqual + 12
5  libcache.dylib                 0x184006bcc _entry_get_optionally_checking_collisions + 164
6  libcache.dylib                 0x1840051b8 cache_get_and_retain + 132
7  CoreFoundation                 0x18455f22c -[NSCache objectForKey:] + 68
8  CoreUI                         0x189146660 -[CUIStructuredThemeStore _canGetRenditionWithKey:isFPO:lookForSubstitutions:] + 360
9  CoreUI                         0x189168f48 -[CUICatalog _resolvedRenditionKeyFromThemeRef:withBaseKey:scaleFactor:deviceIdiom:deviceSubtype:sizeClassHorizontal:sizeClassVertical:memoryClass:graphicsClass:graphicsFallBackOrder:] + 1416
10 CoreUI                         0x1891680fc -[CUICatalog namedLookupWithName:scaleFactor:deviceIdiom:deviceSubtype:sizeClassHorizontal:sizeClassVertical:] + 148
11 UIKit                          0x189b7d994 __98-[_UIAssetManager imageNamed:scale:idiom:subtype:cachingOptions:sizeClassPair:attachCatalogImage:]_block_invoke + 424
12 UIKit                          0x189b7d734 -[_UIAssetManager imageNamed:scale:idiom:subtype:cachingOptions:sizeClassPair:attachCatalogImage:] + 212
13 UIKit                          0x189c90584 -[UIImageAsset imageWithTraitCollection:] + 404
14 UIKit                          0x1896cf058 -[UIImageView _resolveImageForTrait:] + 460
15 UIKit                          0x1896ce928 -[UIImageView _didMoveFromWindow:toWindow:] + 212
16 UIKit                          0x18931ad7c -[UIView(Internal) _didMoveFromWindow:toWindow:] + 760
17 UIKit                          0x1893a04f8 -[UIControl _didMoveFromWindow:toWindow:] + 80
18 UIKit                          0x18931ad7c -[UIView(Internal) _didMoveFromWindow:toWindow:] + 760
19 UIKit                          0x18931a310 __45-[UIView(Hierarchy) _postMovedFromSuperview:]_block_invoke + 152
20 Foundation                     0x184f4d500 -[NSISEngine withBehaviors:performModifications:] + 168
21 UIKit                          0x18931a194 -[UIView(Hierarchy) _postMovedFromSuperview:] + 532
22 UIKit                          0x189327b80 -[UIView(Internal) _addSubview:positioned:relativeTo:] + 1784
23 UIKit                          0x189420b34 -[UITransitionView transition:fromView:toView:removeFromView:] + 1544
24 UIKit                          0x189420458 -[UIViewControllerBuiltinTransitionViewAnimator animateTransition:] + 2780
25 UIKit                          0x18967ab7c __56-[UIPresentationController runTransitionForCurrentState]_block_invoke + 2228
26 UIKit                          0x1895d0b70 _runAfterCACommitDeferredBlocks + 292
27 UIKit                          0x1895de030 _cleanUpAfterCAFlushAndRunDeferredBlocks + 92
28 UIKit                          0x189311c24 _afterCACommitHandler + 96
29 CoreFoundation                 0x1845e4588 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32
30 CoreFoundation                 0x1845e232c __CFRunLoopDoObservers + 372
31 CoreFoundation                 0x1845e275c __CFRunLoopRun + 928
32 CoreFoundation                 0x184511680 CFRunLoopRunSpecific + 384
33 GraphicsServices               0x185a20088 GSEventRunModal + 180
34 UIKit                          0x189388d90 UIApplicationMain + 204
35 TestDrive                      0x1000a32ec main (AppDelegate.swift:15)
36 libdispatch.dylib              0x1840b28b8 (Missing)

#0. com.apple.libdispatch-manager
0  libsystem_kernel.dylib         0x1841d14fc kevent_qos + 8
1  libdispatch.dylib              0x18409494c _dispatch_mgr_invoke + 232
2  libdispatch.dylib              0x1840837bc _dispatch_source_invoke + 50

#1. com.twitter.crashlytics.ios.MachExceptionServer
0  TestDrive                      0x1000d94c8 CLSProcessRecordAllThreads + 4296103112
1  TestDrive                      0x1000d94c8 CLSProcessRecordAllThreads + 4296103112
2  TestDrive                      0x1000d98e8 CLSProcessRecordAllThreads + 4296104168
3  TestDrive                      0x1000ca5a8 CLSHandler + 4296041896
4  TestDrive                      0x1000c572c CLSMachExceptionServer + 4296021804
5  libsystem_pthread.dylib        0x184297b28 _pthread_body + 156
6  libsystem_pthread.dylib        0x184297a8c _pthread_body + 154
7  libsystem_pthread.dylib        0x184295028 thread_start + 4

#2. com.apple.NSURLConnectionLoader
0  libsystem_kernel.dylib         0x1841b54bc mach_msg_trap + 8
1  libsystem_kernel.dylib         0x1841b5338 mach_msg + 72
2  CoreFoundation                 0x1845e4ac0 __CFRunLoopServiceMachPort + 196
3  CoreFoundation                 0x1845e27c4 __CFRunLoopRun + 1032
4  CoreFoundation                 0x184511680 CFRunLoopRunSpecific + 384
5  CFNetwork                      0x184c81434 +[NSURLConnection(Loader) _resourceLoadLoop:] + 412
6  Foundation                     0x184fefc40 __NSThread__start__ + 1000
7  libsystem_pthread.dylib        0x184297b28 _pthread_body + 156
8  libsystem_pthread.dylib        0x184297a8c _pthread_body + 154
9  libsystem_pthread.dylib        0x184295028 thread_start + 4

#3. com.apple.CFSocket.private
0  libsystem_kernel.dylib         0x1841d0368 __select + 8
1  CoreFoundation                 0x1845eb028 __CFSocketManager + 648
2  libsystem_pthread.dylib        0x184297b28 _pthread_body + 156
3  libsystem_pthread.dylib        0x184297a8c _pthread_body + 154
4  libsystem_pthread.dylib        0x184295028 thread_start + 4

#4. com.apple.coremedia.player.async
0  libsystem_kernel.dylib         0x1841b54f8 semaphore_wait_trap + 8
1  libdispatch.dylib              0x18409255c _dispatch_semaphore_wait_slow + 244
2  MediaToolbox                   0x18a119454 fpa_AsyncMovieControlThread + 1948
3  CoreMedia                      0x1865ea980 figThreadMain + 272
4  libsystem_pthread.dylib        0x184297b28 _pthread_body + 156
5  libsystem_pthread.dylib        0x184297a8c _pthread_body + 154
6  libsystem_pthread.dylib        0x184295028 thread_start + 4

#5. com.apple.CoreMotion.MotionThread
0  libsystem_kernel.dylib         0x1841b54bc mach_msg_trap + 8
1  libsystem_kernel.dylib         0x1841b5338 mach_msg + 72
2  CoreFoundation                 0x1845e4ac0 __CFRunLoopServiceMachPort + 196
3  CoreFoundation                 0x1845e27c4 __CFRunLoopRun + 1032
4  CoreFoundation                 0x184511680 CFRunLoopRunSpecific + 384
5  CoreFoundation                 0x18455ee2c CFRunLoopRun + 112
6  CoreMotion                     0x18a03e22c (null) + 95286384
7  libsystem_pthread.dylib        0x184297b28 _pthread_body + 156
8  libsystem_pthread.dylib        0x184297a8c _pthread_body + 154
9  libsystem_pthread.dylib        0x184295028 thread_start + 4

#6. Thread
0  libsystem_kernel.dylib         0x1841d0b6c __workq_kernreturn + 8
1  libsystem_pthread.dylib        0x184295530 _pthread_wqthread + 1284
2  libsystem_pthread.dylib        0x184295020 start_wqthread + 4

#7. com.apple.camera.avcapturesession
0  libsystem_kernel.dylib         0x1841b54bc mach_msg_trap + 8
1  libsystem_kernel.dylib         0x1841b5338 mach_msg + 72
2  CoreFoundation                 0x1845e4ac0 __CFRunLoopServiceMachPort + 196
3  CoreFoundation                 0x1845e27c4 __CFRunLoopRun + 1032
4  CoreFoundation                 0x184511680 CFRunLoopRunSpecific + 384
5  AVFoundation                   0x18a8e61dc -[AVRunLoopCondition _waitInMode:untilDate:] + 432
6  AVFoundation                   0x18a8ce960 -[AVCaptureSession _stopFigCaptureSession] + 412
7  AVFoundation                   0x18a8ceb34 -[AVCaptureSession _setRunning:] + 216
8  CameraKit                      0x18d1dcce0 __35-[CMKCaptureController stopPreview]_block_invoke
9  libdispatch.dylib              0x184081630 _dispatch_call_block_and_release + 24
10 libdispatch.dylib              0x1840815f0 _dispatch_client_callout + 16
11 libdispatch.dylib              0x18408d634 _dispatch_queue_drain + 864
12 libdispatch.dylib              0x1840850f4 _dispatch_queue_invoke + 464
13 libdispatch.dylib              0x1840815f0 _dispatch_client_callout + 16
14 libdispatch.dylib              0x18408fa88 _dispatch_root_queue_drain + 2140
15 libdispatch.dylib              0x18408f224 _dispatch_worker_thread3 + 112
16 libsystem_pthread.dylib        0x184295470 _pthread_wqthread + 1092
17 libsystem_pthread.dylib        0x184295020 start_wqthread + 4

Crashed: NSOperationQueue 0x15d5754b0 :: NSOperation 0x15e9b8460 (QOS: LEGACY)
0  TestDrive                      0x1000b597c VerifyDriverViewController.(runRequestOnBackgroundThread(NSMutableURLRequest) -> ()).(closure #2) (VerifyDriverViewController.swift:491)
1  CFNetwork                      0x184c0f344 __75-[__NSURLSessionLocal taskForClass:request:uploadFile:bodyData:completion:]_block_invoke + 32
2  CFNetwork                      0x184c21cc4 __49-[__NSCFLocalSessionTask _task_onqueue_didFinish]_block_invoke + 296
3  Foundation                     0x184fd4334 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 16
4  Foundation                     0x184f27100 -[NSBlockOperation main] + 96
5  Foundation                     0x184f17348 -[__NSOperationInternal _start:] + 604
6  Foundation                     0x184fd6728 __NSOQSchedule_f + 224
7  libdispatch.dylib              0x1840815f0 _dispatch_client_callout + 16
8  libdispatch.dylib              0x18408d634 _dispatch_queue_drain + 864
9  libdispatch.dylib              0x1840850f4 _dispatch_queue_invoke + 464
10 libdispatch.dylib              0x18408f504 _dispatch_root_queue_drain + 728
11 libdispatch.dylib              0x18408f224 _dispatch_worker_thread3 + 112
12 libsystem_pthread.dylib        0x184295470 _pthread_wqthread + 1092
13 libsystem_pthread.dylib        0x184295020 start_wqthread + 4

#9. Thread
0  libsystem_kernel.dylib         0x1841d0b6c __workq_kernreturn + 8
1  libsystem_pthread.dylib        0x184295530 _pthread_wqthread + 1284
2  libsystem_pthread.dylib        0x184295020 start_wqthread + 4

#10. Thread
0  libsystem_kernel.dylib         0x1841d0b6c __workq_kernreturn + 8
1  libsystem_pthread.dylib        0x184295530 _pthread_wqthread + 1284
2  libsystem_pthread.dylib        0x184295020 start_wqthread + 4

#11. Thread
0  libsystem_kernel.dylib         0x1841d0b6c __workq_kernreturn + 8
1  libsystem_pthread.dylib        0x184295530 _pthread_wqthread + 1284
2  libsystem_pthread.dylib        0x184295020 start_wqthread + 4
sebastiansson
  • 177
  • 14
  • Which line is line 491? – kennytm Jun 28 '16 at 08:40
  • 1
    You are force unwrapping data in the completion closure: `self.analyzeResults(data!)`. You need to check if there isn't an error first or check if data is not nil. I advise people to not force unwrap because it is bad practice. – Gwynant Jones Jun 28 '16 at 08:51
  • @kennytm Sorry about that, line 491 is: dispatch_async(dispatch_get_main_queue(), { //Here goes some regex }) – sebastiansson Jun 28 '16 at 08:56
  • 1
    Do you know if the app is visible (in foreground) when the crash happens? – kennytm Jun 28 '16 at 09:06
  • @kennytm Always in the foreground. – sebastiansson Jun 28 '16 at 09:18
  • Is there any other information from the crash report other than the stack trace? – kennytm Jun 28 '16 at 09:30
  • 1
    The crash doesn't appear to bet related to network. It is UI update related, looks like in UIImage imagedNames. What is the code in the diapatch_async – Paulw11 Jun 28 '16 at 09:43
  • you have not provided the header: is that SIGABRT SIGSEGV, what's the signal? – Anton Tropashko Aug 30 '17 at 12:22
  • @Paulw11 if it would be related to UIImage then the `.main` thread would be marked as "Crashed". However in this case the crash happened on `Crashed: NSOperationQueue 0x15d5754b0 :: NSOperation 0x15e9b8460 (QOS: LEGACY)` this thread. – Legonaftik May 17 '21 at 22:00
  • That `data!` force unwrap screams “crash” at me. Check for errors and conditionally unwrap. – Paulw11 May 17 '21 at 23:08
  • Also there is no need to dispatch the function onto another queue only to then dispatch the UI update on the main queue. The network operation will use a non-main queue already so dispatching the whole function is unnecessary – Paulw11 May 17 '21 at 23:10

1 Answers1

0

Here's the top of the stack trace from the thread which caused the crash:

Crashed: NSOperationQueue 0x15d5754b0 :: NSOperation 0x15e9b8460 (QOS: LEGACY)
0  TestDrive                      0x1000b597c VerifyDriverViewController.(runRequestOnBackgroundThread(NSMutableURLRequest) -> ()).(closure #2) (VerifyDriverViewController.swift:491)
1  CFNetwork                      0x184c0f344 __75-[__NSURLSessionLocal taskForClass:request:uploadFile:bodyData:completion:]_block_invoke + 32
...

It looks like the crash happened inside of the following closure:

{ data, response, error -> Void in
    self.analyzeResults(data!)
}

but before entering the analyzeResults(dataToParse: NSData) function. The only obvious issue at the line self.analyzeResults(data!) is that you're force-unwrapping data without checking that it's present.

As you noticed, Apple mentions that under the Low Power Mode the system may:

Pause discretionary and background activities, including networking

So it's possible that because of the Low Power Mode networking paused for your users which led to timeouts for the network requests. With these timeouts your data variable becomes nil and then you get the crash.

Legonaftik
  • 1,350
  • 3
  • 17
  • 33