iOS11 看门狗超时崩溃(0x8badf00d)但代码不在堆栈上

Posted

技术标签:

【中文标题】iOS11 看门狗超时崩溃(0x8badf00d)但代码不在堆栈上【英文标题】:iOS11 watchdog timeout crashes (0x8badf00d) but code not on stack 【发布时间】:2017-09-30 00:58:25 【问题描述】:

我正在调试用户报告我们的应用程序在 ios11 开始时在后台反复退出,即使在活跃使用期间也是如此(例如,用户将我们设置为后台并在几秒钟或一分钟内返回,却发现它重新启动)。崩溃日志都揭示了相同的原因:看门狗超时。以下是此类崩溃日志中的相关信息:

Exception Type:  EXC_CRASH (SIGKILL)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note:  EXC_CORPSE_NOTIFY
Termination Reason: Namespace <0xF>, Code 0x8badf00d
Triggered by Thread:  0

我意识到我们的代码在接收推送通知或后台运行时的运行时间是有限的。我们确实使用了 UIBackgroundTasks(带有Alamofire Networking,FWIW),并且我们确实有执行此操作的过期处理程序:

backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^
    [application endBackgroundTask:backgroundTask];
    backgroundTask = UIBackgroundTaskInvalid; // Set the task to be invalid
    DebugLog(@"Ended because expiration");
];

这些崩溃报告最令人困惑的是,我们的代码在堆栈中无处可寻。从this Apple discussion of the 0x8badf00d exception code可以看出,违规代码其实是在主线程上主动执行的。

但是,在我的例子中,没有一个堆栈曾经执行过我的任何代码。这是一个具有代表性的示例:

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libsystem_kernel.dylib          0x0000000183208bc4 0x183208000 + 3012
1   libsystem_kernel.dylib          0x0000000183208a3c 0x183208000 + 2620
2   CoreFoundation                  0x00000001836b9c4c 0x1835d0000 + 957516
3   CoreFoundation                  0x00000001836b7818 0x1835d0000 + 948248
4   CoreFoundation                  0x00000001835d7e78 0x1835d0000 + 32376
5   GraphicsServices                0x000000018546cf84 0x185462000 + 44932
6   UIKit                           0x000000018d37a0bc 0x18d307000 + 471228
7   MyApp                           0x0000000102a6572c main + 87852 (main.m:22)
8   libdyld.dylib                   0x00000001830fa56c 0x1830f9000 + 5484

Thread 1 name:  com.apple.uikit.eventfetch-thread
Thread 1:
0   libsystem_kernel.dylib          0x0000000183208bc4 0x183208000 + 3012
1   libsystem_kernel.dylib          0x0000000183208a3c 0x183208000 + 2620
2   CoreFoundation                  0x00000001836b9c4c 0x1835d0000 + 957516
3   CoreFoundation                  0x00000001836b7818 0x1835d0000 + 948248
4   CoreFoundation                  0x00000001835d7e78 0x1835d0000 + 32376
5   Foundation                      0x00000001840006e4 0x183ff4000 + 50916
6   Foundation                      0x000000018401fafc 0x183ff4000 + 178940
7   UIKit                           0x000000018ded9630 0x18d307000 + 12396080
8   Foundation                      0x0000000184101860 0x183ff4000 + 1103968
9   libsystem_pthread.dylib         0x000000018333c31c 0x18333a000 + 8988
10  libsystem_pthread.dylib         0x000000018333c1e8 0x18333a000 + 8680
11  libsystem_pthread.dylib         0x000000018333ac28 0x18333a000 + 3112

Thread 2 name:  com.twitter.crashlytics.ios.MachExceptionServer
Thread 2:
0   libsystem_kernel.dylib          0x0000000183208bc4 0x183208000 + 3012
1   libsystem_kernel.dylib          0x0000000183208a3c 0x183208000 + 2620
2   MyApp                           0x0000000102cdaad8 CLSMachExceptionServer + 100
3   libsystem_pthread.dylib         0x000000018333c31c 0x18333a000 + 8988
4   libsystem_pthread.dylib         0x000000018333c1e8 0x18333a000 + 8680
5   libsystem_pthread.dylib         0x000000018333ac28 0x18333a000 + 3112

Thread 3 name:  com.apple.NSURLConnectionLoader
Thread 3:
0   libsystem_kernel.dylib          0x0000000183208bc4 0x183208000 + 3012
1   libsystem_kernel.dylib          0x0000000183208a3c 0x183208000 + 2620
2   CoreFoundation                  0x00000001836b9c4c 0x1835d0000 + 957516
3   CoreFoundation                  0x00000001836b7818 0x1835d0000 + 948248
4   CoreFoundation                  0x00000001835d7e78 0x1835d0000 + 32376
5   CFNetwork                       0x0000000183d41de0 0x183c93000 + 716256
6   Foundation                      0x0000000184101860 0x183ff4000 + 1103968
7   libsystem_pthread.dylib         0x000000018333c31c 0x18333a000 + 8988
8   libsystem_pthread.dylib         0x000000018333c1e8 0x18333a000 + 8680
9   libsystem_pthread.dylib         0x000000018333ac28 0x18333a000 + 3112

Thread 4 name:  AVAudioSession Notify Thread
Thread 4:
0   libsystem_kernel.dylib          0x0000000183208bc4 0x183208000 + 3012
1   libsystem_kernel.dylib          0x0000000183208a3c 0x183208000 + 2620
2   CoreFoundation                  0x00000001836b9c4c 0x1835d0000 + 957516
3   CoreFoundation                  0x00000001836b7818 0x1835d0000 + 948248
4   CoreFoundation                  0x00000001835d7e78 0x1835d0000 + 32376
5   AVFAudio                        0x0000000189615774 0x189591000 + 542580
6   AVFAudio                        0x0000000189640018 0x189591000 + 716824
7   libsystem_pthread.dylib         0x000000018333c31c 0x18333a000 + 8988
8   libsystem_pthread.dylib         0x000000018333c1e8 0x18333a000 + 8680
9   libsystem_pthread.dylib         0x000000018333ac28 0x18333a000 + 3112

Thread 5:
0   libsystem_kernel.dylib          0x0000000183229150 0x183208000 + 135504
1   libsystem_pthread.dylib         0x000000018333ed30 0x18333a000 + 19760
2   libc++.1.dylib                  0x00000001828e3ea4 0x1828dc000 + 32420
3   javascriptCore                  0x000000018b157d00 0x18a812000 + 9723136
4   JavaScriptCore                  0x000000018b157c28 0x18a812000 + 9722920
5   JavaScriptCore                  0x000000018b157f8c 0x18a812000 + 9723788
6   libsystem_pthread.dylib         0x000000018333c31c 0x18333a000 + 8988
7   libsystem_pthread.dylib         0x000000018333c1e8 0x18333a000 + 8680
8   libsystem_pthread.dylib         0x000000018333ac28 0x18333a000 + 3112

Thread 6 name:  WebThread
Thread 6:
0   libsystem_kernel.dylib          0x0000000183208bc4 0x183208000 + 3012
1   libsystem_kernel.dylib          0x0000000183208a3c 0x183208000 + 2620
2   CoreFoundation                  0x00000001836b9c4c 0x1835d0000 + 957516
3   CoreFoundation                  0x00000001836b7818 0x1835d0000 + 948248
4   CoreFoundation                  0x00000001835d7e78 0x1835d0000 + 32376
5   WebCore                         0x000000018bc1c75c 0x18bbdb000 + 268124
6   libsystem_pthread.dylib         0x000000018333c31c 0x18333a000 + 8988
7   libsystem_pthread.dylib         0x000000018333c1e8 0x18333a000 + 8680
8   libsystem_pthread.dylib         0x000000018333ac28 0x18333a000 + 3112

Thread 7 name:  WebCore: LocalStorage
Thread 7:
0   libsystem_kernel.dylib          0x0000000183229150 0x183208000 + 135504
1   libsystem_pthread.dylib         0x000000018333ed30 0x18333a000 + 19760
2   JavaScriptCore                  0x000000018a81fa18 0x18a812000 + 55832
3   JavaScriptCore                  0x000000018b13da04 0x18a812000 + 9615876
4   WebKitLegacy                    0x000000018d00f5fc 0x18cf7c000 + 603644
5   WebKitLegacy                    0x000000018d01226c 0x18cf7c000 + 615020
6   WebKitLegacy                    0x000000018d011998 0x18cf7c000 + 612760
7   JavaScriptCore                  0x000000018a81c010 0x18a812000 + 40976
8   JavaScriptCore                  0x000000018a81bf50 0x18a812000 + 40784
9   libsystem_pthread.dylib         0x000000018333c31c 0x18333a000 + 8988
10  libsystem_pthread.dylib         0x000000018333c1e8 0x18333a000 + 8680
11  libsystem_pthread.dylib         0x000000018333ac28 0x18333a000 + 3112

Thread 8 name:  com.apple.CFSocket.private
Thread 8:
0   libsystem_kernel.dylib          0x0000000183229570 0x183208000 + 136560
1   CoreFoundation                  0x00000001836c2184 0x1835d0000 + 991620
2   libsystem_pthread.dylib         0x000000018333c31c 0x18333a000 + 8988
3   libsystem_pthread.dylib         0x000000018333c1e8 0x18333a000 + 8680
4   libsystem_pthread.dylib         0x000000018333ac28 0x18333a000 + 3112

Thread 9:
0   libsystem_pthread.dylib         0x000000018333ac1c 0x18333a000 + 3100

Thread 10:
0   libsystem_kernel.dylib          0x0000000183229dbc 0x183208000 + 138684
1   libsystem_pthread.dylib         0x000000018333afa0 0x18333a000 + 4000
2   libsystem_pthread.dylib         0x000000018333ac20 0x18333a000 + 3104

Thread 11:
0   libsystem_pthread.dylib         0x000000018333ac1c 0x18333a000 + 3100

Thread 0 crashed with ARM Thread State (64-bit):
    x0: 0x0000000010004005   x1: 0x0000000007000806   x2: 0x0000000000000000   x3: 0x0000000000000c00
    x4: 0x0000000000002b03   x5: 0x00000000ffffffff   x6: 0x0000000000000000   x7: 0x0000000000000000
    x8: 0x00000000fffffbbf   x9: 0x0000000007000000  x10: 0x0000000007000100  x11: 0x0000000000000040
   x12: 0xffffffffffffffff  x13: 0x0000000000000001  x14: 0x01e8540001e85400  x15: 0x0000000000000000
   x16: 0xffffffffffffffe1  x17: 0x00000000ffffffff  x18: 0x0000000000000000  x19: 0x0000000000000000
   x20: 0x00000000ffffffff  x21: 0x0000000000002b03  x22: 0x0000000000000c00  x23: 0x000000016d3aed38
   x24: 0x0000000007000806  x25: 0x0000000000000000  x26: 0x0000000007000806  x27: 0x0000000000000c00
   x28: 0x0000000000000001   fp: 0x000000016d3aec30   lr: 0x0000000183208a3c
    sp: 0x000000016d3aebe0   pc: 0x0000000183208bc4 cpsr: 0x60000000

我的代码中唯一正在运行的部分是 main.m,第 22 行,即

int retVal = UIApplicationMain(argc, argv, nil, @"PSSMyAppDelegate");  

因此,我很困惑我的应用程序如何因违反运行时间而被反复终止,而实际上我的代码似乎都没有运行。 iOS 11 中是否有任何新功能可以改变看门狗进程的行为?如果不是,我如何知道我的代码的哪一部分是因运行时间过长而违规的部分?

【问题讨论】:

【参考方案1】:

您的线程 0 看起来很像我们在 iOS 11 中遇到的崩溃。这是我们的:

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libsystem_kernel.dylib         0x00000001853c4bc4 mach_msg_trap + 8
1   libsystem_kernel.dylib         0x00000001853c4a3c mach_msg + 72
2   CoreFoundation                 0x0000000185875c4c __CFRunLoopServiceMachPort + 196
3   CoreFoundation                 0x0000000185873818 __CFRunLoopRun + 1424
4   CoreFoundation                 0x0000000185793e78 CFRunLoopRunSpecific + 436
5   GraphicsServices               0x0000000187628f84 GSEventRunModal + 100
6   UIKit                         0x000000018f5360bc UIApplicationMain + 208
7   TestCrashInBackground         0x0000000100e8dbac 0x100e88000 + 23468
8   libdyld.dylib                 0x00000001852b656c start + 4

对我们来说,问题在于显示通知会导致应用崩溃(当应用处于后台时)。我们甚至创建了一个测试应用程序(您在上面看到的 TestCrashInBackground),我们可以在其中重现此问题。该应用程序仅显示通知,没有任何后台任务。 测试用例是:

    应用显示通知 用户将应用程序置于后台(按主页键)。 用户锁定屏幕

结果:操作系统会在一段时间(短)时间后终止应用。

我们在发生这种情况后进行了系统诊断,我们可以看到,当我们显示通知时,添加了一个名为“将呈现通知”的断言。

default 2017-10-03 14:32:16.280562 +0200    assertiond  [SpringBoard:53] Attempting to acquire assertion for TestCrashInBack:507: <BKProcessAssertion: 0x101235c90; "will present notification" (notificationAction:30s); id:…E1D79D51D1D9>
default 2017-10-03 14:32:16.281283 +0200    assertiond  [TestCrashInBack:507] Add assertion: <BKProcessAssertion: 0x101235c90; id: 53-96A5F4EA-4C42-4675-97E4-E1D79D51D1D9; name: "will present notification"; state: active; reason: notificationAction; duration: 30.0s> 
    owner = <BSProcessHandle: 0x10110a810; SpringBoard:53; valid: YES>;
    flags = preventSuspend, preventThrottleDownUI, preventIdleSleep, preventSuspendOnSleep;

大约 45 秒后,应用被杀死,因为它“有超过允许时间的活动断言”:

default 2017-10-03 14:33:00.436085 +0200    assertiond  [TestCrashInBack:507] Forcing crash report with description: TestCrashInBack:507 has active assertions beyond permitted time: 
<BKProcessAssertion: 0x101235c90; "will present notification" (notificationAction:30s); id:…E1D79D51D1D9> (owner: SpringBoard:53)

所有这些只是为了显示一个通知...相当严重的错误!

这是添加通知的代码:

UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.body = NSLocalizedString(@"This is test notification", nil);

UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:content.body content:content trigger:[UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1.0 repeats:NO]];
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) 
    NSLog(@"display notification error:%@", error);
];

我已向 Apple (id: 34788843) 提交了一份错误报告,并附上了我们的测试项目和 sysdiagnose。希望他们能尽快解决这个问题。

【讨论】:

【参考方案2】:

我与 Apple 的一位工程师交谈过,他将问题描述如下—— 想象一下我们有这样的方法:

- (void)startTask 
   self.bgTask = [application beginBackgroundTaskWithExpirationHandler:^
      [application endBackgroundTask:self.bgTask];
      self.bgTask = UIBackgroundTaskInvalid;
   ];

然后代码会调用它两次(比如说,因为我们收到了两次对 didReceiveRemoteNotification 的调用):

[self startTask];
[self startTask];

根据我们采访的工程师的说法,该应用程序随后将完全按照我们所看到的方式崩溃。

此外,从技术上讲,只要我们在结束第一个任务之前创建第二个任务,我们的应用就会崩溃。除非后台任务直接附加到其他直接管理其生命周期并且无法“拥有”多个任务的对象(例如,在创建时开始 1 个单个任务并在完成/销毁时结束它的独立操作),否则它非常难以避免“任务重入”的问题。

更好的选择是在任务到期时依赖局部变量,将您的对象成员变量排除在到期处理程序之外。

【讨论】:

以上是关于iOS11 看门狗超时崩溃(0x8badf00d)但代码不在堆栈上的主要内容,如果未能解决你的问题,请参考以下文章

0x8badf00d 在后台获取监听位置后崩溃

iOS 应用程序因终止原因而崩溃:命名空间 SPRINGBOARD,代码 0x8badf00d

奇怪的 iPhone 0x8badf00d 崩溃报告

我在 iPhone 应用程序中收到错误 0x8badf00d,这不是通常的嫌疑人

Iphone,我怎样才能避免看门狗杀死我的应用程序需要很长时间才能启动?

Crash分析