Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CoreMotion crash(iPad-only) on invoking stopDeviceMotionUpdates

We have an instance of CMMotionManager in our app which we use to get sensor updates at a frequency of 5Hz. Following is the code we use to start motion updates:

[self.motionManager
startDeviceMotionUpdatesUsingReferenceFrame:
CMAttitudeReferenceFrameXMagneticNorthZVertical
toQueue:operationQueue
withHandler:^(CMDeviceMotion *motion, NSError *error) {
if (!error) { 
   [self doSomethingWithMotion:motion];
} else { ... }

The above method is always invoked on the main thread.

Now, once we are done with our task, we stop motion updates by calling the following method, again on the main thread :

- (void)stopMotionUpdates {
    // This might get called on concurrent threads.
    // So better using sync block + make it idempotent
    @synchronized(self) {
        if (_motionManager.deviceMotionActive) {
            [_motionManager stopDeviceMotionUpdates];
            _prevPoint = nil;
        }
    }
}

The issue we are facing is that the stopMotionUpdates crashes, that too, only in iPads. We have tested this extensively on iPhones and iPads with different OS versions and we get the crash only on iPads (mini 1,2 and retina/non-retina) for both iOS7 and iOS8. Also, we cannot reproduce the crash on all iPads which we use for testing, but only a few. Following are the crash logs for main and the crashed thread:

Thread : com.apple.main-thread
0  libsystem_kernel.dylib         0x00000001935f1cdc semaphore_wait_trap + 8
1  libdispatch.dylib              0x00000001934fbb3c _dispatch_semaphore_wait_slow + 252
2  CoreMotion                     0x0000000186bf67d4 (null)
3  CoreMotion                     0x0000000186be3698 (null)
4  MyApp                          0x00000001002f7434 -[MyAppMotionManager stopMotionUpdates]
...
...
12 MyApp                          0x00000001002e94f8 __getDispatchTimer_block_invoke
13 libdispatch.dylib              0x00000001934f3fd4 _dispatch_client_callout + 16
14 libdispatch.dylib              0x00000001934f5b90 _dispatch_source_invoke + 500
15 libdispatch.dylib              0x00000001934f7180 _dispatch_main_queue_callback_4CF + 244
16 CoreFoundation                 0x00000001864fec2c __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
17 CoreFoundation                 0x00000001864fcf6c __CFRunLoopRun + 1452
18 CoreFoundation                 0x000000018643dc20 CFRunLoopRunSpecific + 452
19 GraphicsServices               0x000000018c0ddc0c GSEventRunModal + 168
20 UIKit                          0x000000018956efdc UIApplicationMain + 1156
21 MyApp                          0x00000001000c9850 main (main.m:14)
22 libdyld.dylib                  0x000000019350faa0 start + 4

EXC_BREAKPOINT UNKNOWN at 0x0000000186c257ac
Thread : Crashed: Thread
0  CoreMotion                     0x0000000186c257ac (null) + 110504
1  CoreMotion                     0x0000000186c25774 (null) + 110448
2  CoreMotion                     0x0000000186bf3c84 (null)
3  CoreMotion                     0x0000000186bf67ec (null)
4  CoreMotion                     0x0000000186bf3b80 (null)
5  CoreMotion                     0x0000000186c24c48 (null) + 107588
6  CoreMotion                     0x0000000186bf67ec (null)
7  CoreMotion                     0x0000000186c24ba4 (null) + 107424
8  CoreMotion                     0x0000000186be3b9c (null)
9  CoreMotion                     0x0000000186bf6860 (null)
10 CoreFoundation                 0x00000001864ff680 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 20
11 CoreFoundation                 0x00000001864fe838 __CFRunLoopDoBlocks + 300
12 CoreFoundation                 0x00000001864fd0a4 __CFRunLoopRun + 1764
13 CoreFoundation                 0x000000018643dc20 CFRunLoopRunSpecific + 452
14 CoreFoundation                 0x00000001864932a8 CFRunLoopRun + 112
15 CoreMotion                     0x0000000186bf653c (null)
16 libsystem_pthread.dylib        0x000000019368be1c _pthread_body + 168
17 libsystem_pthread.dylib        0x000000019368bd74 _pthread_body

Since we reference self in the motion update handler block, the object shouldn't be deallocated till the entire queue is flushed. Any help is appreciated :)

like image 702
Yogesh Maheshwari Avatar asked Apr 25 '15 06:04

Yogesh Maheshwari


2 Answers

You might be overloading the main thread.

  • As a rule of thumb, you should never do anything on the main thread that takes more than or about a second.

  • The main thread is responsible for running the user interface. If you block the main thread for any significant amount of time, the user interface becomes unacceptably unresponsive.

  • watchdog — In order to keep the user interface responsive, iOS includes a watchdog mechanism. If your application fails to respond to certain user interface events (launch, suspend, resume, terminate) in time or some operation takes little bit more time on the main thread then the watchdog will kill your application. The amount of time the watchdog gives you is not formally documented, but it's always less.

  • Any such operation must be done on a background thread and you could easily do it using

    • dispatch_async

    • NSOperationQueue

    • performSelectorInBackground

Hope this helps.

like image 91
Durai Amuthan.H Avatar answered Oct 28 '22 00:10

Durai Amuthan.H


Your crash comes from the @synchronized directive. As you can see the main thread is executing your code in @synchronized. This locks the view controller, from being accessed by any other thread.

The thread that is crashed is for the CoreMotion and I suppose it was trying to give updates on the device motion.

I believe the crash is happening just in some cases when the CoreMotion happens to try to updates in the same time your main thread runs through synchronized.

like image 24
pteofil Avatar answered Oct 28 '22 00:10

pteofil