CoreMotion崩溃(仅限iPad)调用stopDeviceMotionUpdates

Yog*_*ari 15 multithreading objective-c ipad ios core-motion

我们的应用程序中有一个CMMotionManager实例,我们用它来获取频率为5Hz的传感器更新.以下是我们用于启动动画更新的代码:

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

始终在主线程上调用上述方法.

现在,一旦完成了我们的任务,我们再次在主线程上调用以下方法来停止动作更新:

- (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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我们面临的问题是stopMotionUpdates崩溃,这也只是在iPad中崩溃.我们已经在具有不同操作系统版本的iPhone和iPad上进行了广泛的测试,我们只能在iOS7和iOS8的iPad(迷你1,2和视网膜/非视网膜)上进行崩溃.此外,我们无法在我们用于测试的所有iPad上重现崩溃,但只有少数.以下是main和崩溃线程的崩溃日志:

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
Run Code Online (Sandbox Code Playgroud)

由于我们在运动更新处理程序块中引用self,因此在刷新整个队列之前不应释放该对象.任何帮助表示赞赏:)

pte*_*fil 2

你的崩溃来自@synchronized指令。正如您所看到的,主线程正在执行@synchronized. 这会锁定视图控制器,防止其被任何其他线程访问。

崩溃的线程是针对CoreMotion 的,我想它正在尝试提供有关设备运动的更新。

我相信在某些情况下,当CoreMotion碰巧尝试在主线程运行同步时进行更新时,就会发生崩溃。