watchdog
2020-07-07 22:44:50 # iOS

简介

为了防止一个应用程序占用过多的系统资源,苹果设计一个监督机构 watchdog ,音译:看门狗机制。

用户希望应用程序快速启动,并对触摸和手势做出响应。操作系统使用一个监督机构来监控启动时间和应用程序的响应,如果超出了该场景下所规定的运行时间,该机制就会终止无响应的应用程序。

watchdog 完整的信息:

1
2
3
4
5
6
Exception Type:  EXC_CRASH (SIGKILL)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Reason: Namespace SPRINGBOARD, Code 0x8badf00d
Termination Description: SPRINGBOARD, <RBSTerminateContext| domain:10 code:0x8BADF00D explanation:scene-update watchdog transgression: application<com.kaike.online>:745 exhausted real (wall clock) time allowance of 10.00 seconds | ProcessVisibility: Background | ProcessState: Running | WatchdogEvent: scene-update | WatchdogVisibility: Background | WatchdogCPUStatistics: ( | "Elapsed total CPU time (seconds): 20.230 (user 20.230, system 0.000), 34% CPU", | "Elapsed application CPU time (seconds): 0.001, 0% CPU" | ) reportType:CrashLog maxTerminationResistance:Interactive>
Triggered by Thread: 0

通俗讲:

为了避免应用陷入错误状态导致界面无响应,Apple 设计了 watchdog 机制。一旦超时,强制杀死进程。在不同的生命周期,触发 watchdog 机制的超时时间有所不同:

生命周期 超时时间
启动 Launch 20s
恢复 Resume 10s
悬挂 Suspend 10s
退出Quit 6s
后台 Background 10min

watchdog 的终止使用崩溃报告的终止原因中的代码是 0x8badf00d (发音为“吃了不好的食物”)

1
2
3
4
Exception Type:  EXC_CRASH (SIGKILL)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Reason: Namespace SPRINGBOARD, Code 0x8badf00d

watchdog 终止长时间阻塞主线程的应用程序。有很多方法可以延长阻塞主线程,例如:

  • 同步网络
  • 处理大量数据

  • 同步触发大型核心数据存储的轻量级迁移

  • 使用Vision进行分析请求。

解读App响应式 watchdog 信息

当应用程序启动或响应事件缓慢时,崩溃报告中的终止信息包含有关应用程序如何花费时间的重要信息。

崩溃信息一

例如,卡顿时挂起App在崩溃报告中具有以下内容:

1
2
3
4
5
6
7
8
9
Termination Description: SPRINGBOARD, <RBSTerminateContext| domain:10 code:0x8BADF00D explanation:scene-update watchdog transgression: application<com.example.MyCoolApp>:745 exhausted real (wall clock) time allowance of 10.00 seconds 
| ProcessVisibility: Background
| ProcessState: Running
| WatchdogEvent: scene-update
| WatchdogVisibility: Background
| WatchdogCPUStatistics: (
| "Elapsed total CPU time (seconds): 20.230 (user 20.230, system 0.000), 34% CPU",
| "Elapsed application CPU time (seconds): 0.001, 0% CPU"
| )

上述描述中可以看出:WatchdogEventscene-update ,说明应用程序是在场景更新 时终止的,原因是没有足够快地更新其UI,因为主线程太忙。

崩溃信息二

在App启动后没有快速呈现UI,在崩溃报告中具有以下内容:

1
2
3
4
5
6
7
8
9
10
11
Termination Description: SPRINGBOARD, 
scene-create watchdog transgression: application<com.example.MyCoolApp>:667
exhausted real (wall clock) time allowance of 19.97 seconds
| ProcessVisibility: Foreground
| ProcessState: Running
| WatchdogEvent: scene-create
| WatchdogVisibility: Foreground
| WatchdogCPUStatistics: (
| "Elapsed total CPU time (seconds): 15.290 (user 15.290, system 0.000), 28% CPU",
| "Elapsed application CPU time (seconds): 0.367, 1% CPU"
| )

WatchdogEvent: scene-create 可以看出是在场景创建时终止的,原因是没有在允许的启动时间内将UI的第一帧渲染到屏幕上。

崩溃信息中的信息解析

1.1 Elapsed total CPU time

Elapsed total CPU time 显示CPU在挂钟时间内系统上的所有进程运行了多少时间。

此CPU时间以及应用程序CPU时间适用于跨CPU内核的总CPU利用率,可能超过100%。例如,如果一个CPU内核利用率为100%,第二个CPU内核利用率为20%,则总CPU利用率为120%。

1.2 Elapsed application CPU time

Elapsed application CPU time 显示应用程序在挂钟时间内在CPU上运行所花费的时间。

如果此数字处于任一极端,则表明存在问题。如果数字很高,则应用程序正在其所有线程中执行大量工作(该数字聚合所有线程,并且不特定于主线程。)

如果此数字较低,则该应用程序大部分处于空闲状态,因为它正在等待系统资源,例如网络连接。

解决方法

  • 异步请求
  • 不要使用 SCNetworkReachability,而是使用 NWPathMonitor 在网络路径更改时接收更新。系统在您调用 start(queue:) 时传入的队列上提供更新,因此路径更新功能安全地脱离主线程。

  • 在辅助线程中执行同步网络

  • 大多数情况下不建议手动解析 DNS。使用 URLSession 让系统代表您处理 DNS 解析。如果切换非常困难,并且您仍然需要手动更改 DNS 地址,请使用异步 API,如 CFHost 或 中的 API

Addressing Watchdog Terminations