GCD dispatch_after调用导致SIGBUS信号

时间:2012-06-25 01:06:54

标签: ios grand-central-dispatch uiapplicationdelegate

当我的应用程序被加载以执行某些行为时,我正在使用GCD的dispatch_after方法。预期的行为是从applicationDidFinishLaunchingWithOptions结束等待3秒以执行在后台队列中运行的选择器。

我的测试设备上没有遇到任何崩溃,但我有未捕获的SIGBUS信号的用户崩溃报告,原因是BUS_ADRALN异常。根据我对此代码的理解,BUS_ADRALN错误表示地址对齐错误。

这就是我创建计时器的方式:

double delayInSeconds = 3.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),
                     ^(void){
                         [self methodToPerformInBackground];
                     });

可能导致此次崩溃的原因是什么?

由于多线程错误可能是一种奇怪的野兽,我会抛弃一些我一直在脑子里徘徊的想法。

  • 我是在致电[self performSelectorOnMainThread:withObject:waitUntilDone]时打电话给我的。在以这种方式调用的选择器中执行此操作是否存在问题?
  • 由于我正在调用dispatch_get_global_queue而不是dispatch_create_queue,因此我不需要保留此方法返回的队列。这个推理是否正确?
  • 在此代码中,self是应用程序委托。在应用程序进入后台或终止后,是否会导致尝试执行阻止?应用程序会在关闭时自动清理任何已调度的块吗?
  • 调用方法内部的某些内容导致崩溃,但GCD没有为其提供堆栈跟踪。

编辑:我宁愿不包含在块中调用的代码,因为我不相信这是主要问题。这是堆栈跟踪。线程0上的崩溃使得好像问题出现在GCD中,而不是块中调用的代码。

编辑#2:我在通过更多崩溃报告后分享了奇怪的消息。此崩溃仅出现在运行iOS 4.2.X及更低版本的用户身上。由于iOS 4.0及更高版本支持GCD,我的猜测是在4.3中修补了一个错误。

Thread 0 Crashed:
0  libSystem.B.dylib                  0x35e5fb10 _dispatch_retain + 0
1  libSystem.B.dylib                  0x35e5df8c dispatch_after_f + 80
2  libSystem.B.dylib                  0x35e5e070 dispatch_after + 72
3  MyApplication                              0x0000466c -[MyApplicationDelegate applicationDidFinishLaunchingPart2:] (MyApplicationDelegate.m:366)
4  CoreFoundation                      0x37538f79 -[NSObject(NSObject) performSelector:withObject:] + 25
5  Foundation                          0x35171e6d __NSThreadPerformPerform + 273
6  CoreFoundation                      0x375518d1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
7  CoreFoundation                      0x37521ecd __CFRunLoopDoSources0 + 385
8  CoreFoundation                      0x375216f9 __CFRunLoopRun + 265
9  CoreFoundation                      0x3752150b CFRunLoopRunSpecific + 227
10  CoreFoundation                      0x37521419 CFRunLoopRunInMode + 61
11  GraphicsServices                    0x33e76d24 GSEventRunModal + 196
12  UIKit                              0x3591d57c -[UIApplication _run] + 588
13  UIKit                              0x3591a558 UIApplicationMain + 972
14  MyApplication                              0x00003024 main (main.m:113)

Thread 1:
0  libSystem.B.dylib                  0x35d8f974 kevent + 24
1  libSystem.B.dylib                  0x35e5dd70 _dispatch_queue_invoke + 104
2  libSystem.B.dylib                  0x35e5d790 _dispatch_worker_thread2 + 128
3  libSystem.B.dylib                  0x35de6978 _pthread_wqthread + 400

Thread 2:
0  libSystem.B.dylib                  0x35de72fc __workq_kernreturn + 8

Thread 3:
0  libSystem.B.dylib                  0x35d5b3b0 mach_msg_trap + 20
1  CoreFoundation                      0x37521f83 __CFRunLoopServiceMachPort + 95
2  CoreFoundation                      0x37521787 __CFRunLoopRun + 407
3  CoreFoundation                      0x3752150b CFRunLoopRunSpecific + 227
4  CoreFoundation                      0x37521419 CFRunLoopRunInMode + 61
5  WebCore                            0x3318bd1c _ZL12RunWebThreadPv + 532
6  libSystem.B.dylib                  0x35de5b4c _pthread_start + 372

Thread 4:
0  libSystem.B.dylib                  0x35d5b3b0 mach_msg_trap + 20
1  CoreFoundation                      0x37521f83 __CFRunLoopServiceMachPort + 95
2  CoreFoundation                      0x37521787 __CFRunLoopRun + 407
3  CoreFoundation                      0x3752150b CFRunLoopRunSpecific + 227
4  CoreFoundation                      0x37521419 CFRunLoopRunInMode + 61
5  Foundation                          0x3517ec55 +[NSURLConnection(NSURLConnectionReallyInternal) _resourceLoadLoop:] + 217
6  Foundation                          0x3515cb91 -[NSThread main] + 49
7  Foundation                          0x35155b97 __NSThread__main__ + 915
8  libSystem.B.dylib                  0x35de5b4c _pthread_start + 372

1 个答案:

答案 0 :(得分:1)

DISPATCH_QUEUE_PRIORITY_BACKGROUND是iOS 5.0+的一项功能。如果您尝试在iOS 4.x上使用它,它将为NULL(当您尝试保留它时会崩溃,因为GCD是一个C库,并且使用NULL的方式不安全在objective-c中使用nil。有关详细信息,请参阅this answer。解决方案是使用低优先级,或使用预处理器指令在两者之间切换。