我正面临一个问题,没有任何解决方案(还)。在用户按下Home按钮后,我正在使用后台任务处理程序来启动一些数据获取。代码类似于:
-(void)startRequest {
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}];
//..
//Fetch data with NSURLRequest / delegate method
//..
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
if ([delegate respondsToSelector:delegateErrorMethod])
[delegate performSelector:delegateErrorMethod];
UIApplication *app = [UIApplication sharedApplication];
if (bgTask != UIBackgroundTaskInvalid) {
dispatch_async(dispatch_get_main_queue(), ^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if([delegate respondsToSelector:delegateMethod])
[delegate performSelector:delegateMethod withObject:self];
UIApplication *app = [UIApplication sharedApplication];
if (bgTask != UIBackgroundTaskInvalid) {
dispatch_async(dispatch_get_main_queue(), ^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}
}
它运行良好,但有时(没有任何问题或原因,所以它真的无法预测)应用程序崩溃时出现以下崩溃日志:
Application Specific Information:
MyBackgroundTest[7745] has active assertions beyond permitted time:
{(
<SBProcessAssertion: 0x90e65e0> identifier: UIKitBackgroundCompletionTask process: MyBackgroundTest[7745] permittedBackgroundDuration: 600.000000 reason: finishTask owner pid:7745 preventSuspend preventIdleSleep
)}
Elapsed total CPU time (seconds): 0.010 (user 0.010, system 0.000), 100% CPU
Elapsed application CPU time (seconds): 0.000, 0% CPU
Thread 0:
0 libSystem.B.dylib 0x33b5d268 mach_msg_trap + 20
1 libSystem.B.dylib 0x33b5f354 mach_msg + 44
2 CoreFoundation 0x33a48648 __CFRunLoopServiceMachPort + 88
3 CoreFoundation 0x33a47ed2 __CFRunLoopRun + 350
4 CoreFoundation 0x33a47c80 CFRunLoopRunSpecific + 224
5 CoreFoundation 0x33a47b88 CFRunLoopRunInMode + 52
6 GraphicsServices 0x33b0e4a4 GSEventRunModal + 108
7 GraphicsServices 0x33b0e550 GSEventRun + 56
8 UIKit 0x32099322 -[UIApplication _run] + 406
9 UIKit 0x32096e8c UIApplicationMain + 664
10 MyBackgroundTest 0x00002d64 0x1000 + 7524
11 MyBackgroundTest 0x00002d18 0x1000 + 7448
Thread 1:
0 libSystem.B.dylib 0x33b89974 kevent + 24
1 libSystem.B.dylib 0x33c33704 _dispatch_mgr_invoke + 88
2 libSystem.B.dylib 0x33c33174 _dispatch_queue_invoke + 96
3 libSystem.B.dylib 0x33c32b98 _dispatch_worker_thread2 + 120
4 libSystem.B.dylib 0x33bd724a _pthread_wqthread + 258
5 libSystem.B.dylib 0x33bcf970 start_wqthread + 0
Thread 2:
0 libSystem.B.dylib 0x33b5d268 mach_msg_trap + 20
1 libSystem.B.dylib 0x33b5f354 mach_msg + 44
2 CoreFoundation 0x33a48648 __CFRunLoopServiceMachPort + 88
3 CoreFoundation 0x33a47ed2 __CFRunLoopRun + 350
4 CoreFoundation 0x33a47c80 CFRunLoopRunSpecific + 224
5 CoreFoundation 0x33a47b88 CFRunLoopRunInMode + 52
6 WebCore 0x304df124 RunWebThread(void*) + 332
7 libSystem.B.dylib 0x33bd6886 _pthread_start + 242
8 libSystem.B.dylib 0x33bcba88 thread_start + 0
Thread 3:
0 libSystem.B.dylib 0x33b5d268 mach_msg_trap + 20
1 libSystem.B.dylib 0x33b5f354 mach_msg + 44
2 CoreFoundation 0x33a48648 __CFRunLoopServiceMachPort + 88
3 CoreFoundation 0x33a47ed2 __CFRunLoopRun + 350
4 CoreFoundation 0x33a47c80 CFRunLoopRunSpecific + 224
5 CoreFoundation 0x33a47b88 CFRunLoopRunInMode + 52
6 Foundation 0x336465f6 +[NSURLConnection(NSURLConnectionReallyInternal) _resourceLoadLoop:] + 206
7 Foundation 0x33624192 -[NSThread main] + 38
8 Foundation 0x3361d242 __NSThread__main__ + 966
9 libSystem.B.dylib 0x33bd6886 _pthread_start + 242
10 libSystem.B.dylib 0x33bcba88 thread_start + 0
Thread 4:
0 libSystem.B.dylib 0x33b8168c select$DARWIN_EXTSN + 20
1 CoreFoundation 0x33a7f662 __CFSocketManager + 582
2 libSystem.B.dylib 0x33bd6886 _pthread_start + 242
3 libSystem.B.dylib 0x33bcba88 thread_start + 0
Thread 5:
0 libSystem.B.dylib 0x33bd79e0 __workq_kernreturn + 8
1 libSystem.B.dylib 0x33bd7364 _pthread_wqthread + 540
2 libSystem.B.dylib 0x33bcf970 start_wqthread + 0
Thread 6:
0 libSystem.B.dylib 0x33bd79e0 __workq_kernreturn + 8
1 libSystem.B.dylib 0x33bd7364 _pthread_wqthread + 540
2 libSystem.B.dylib 0x33bcf970 start_wqthread + 0
Unknown thread crashed with unknown flavor: 5, state_count: 1
更新:似乎与此问题相关的更接近的线程已打开here。 该错误与重定向http连接有关,包括异步和同步NRURL操作。也许,既然NSURLConnection继承了基础框架,那么这个bug也会出现在iPhone上吗?
openradar at:1062401
答案 0 :(得分:8)
我的调查显示,无论出于什么原因,您都会得到以下例外情况:
TMS[13544] has active assertions beyond permitted time:
{(
<SBProcessAssertion: 0x8cb6040> identifier: UIKitBackgroundCompletionTask process: TMS[13544] permittedBackgroundDuration: 600.000000 reason: finishTask owner pid:13544 preventSuspend preventIdleSleep
)}
如果代码没有执行`endBackgroundTask:'方法。
这意味着使用beginBackgroundTaskWithExpirationHandler:' call MUST be ended with
endBackgroundTask:'创建的每个后台任务。
仔细检查`endBackgroundTask:'是否使用正确的任务ID调用。
答案 1 :(得分:1)
当后台任务未及时结束时,会导致此异常。虽然我无法100%肯定,但我相信这种特殊的崩溃正在发生,因为你传入beginBackgroundTaskWithExpirationHandler:
的阻止,如果连接尚未完成并且系统想要结束你的后台任务,则调用该阻塞。
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}];
- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void (^)(void))handler
的文档说明了handler
:“您应该使用此处理程序来清理并标记后台任务的结束”。
由于dispatch_async
调用,在调用此块时,您实际上并未结束任务。在此块调用返回之后(并且运行dispatch_async
块),您不会结束任务。我相信大部分时间都有足够的时间让你的第二个块在看门狗关闭你的应用程序之前运行,但有时却没有。所以你应该做的就是立即结束后台任务,然后为你需要做的任何其他清理工作dispatch_async
:
UIApplication *app = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier tid = bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:tid];
dispatch_async(dispatch_get_main_queue(), ^{
bgTask = UIBackgroundTaskInvalid;
});
}];
此外,文档说:“处理程序在主线程上同步调用”,因此您根本不需要执行dispatch_async
。你可以这么做:
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];