RFC-0178:每个作业有多个调试异常渠道 | |
---|---|
状态 | 已接受 |
领域 |
|
说明 | Zircon 允许对一个作业使用多个调试异常通道。 |
问题 | |
Gerrit 更改 | |
作者 | |
审核人 | |
提交日期(年-月-日) | 2022-06-08 |
审核日期(年-月-日) | 2022-07-12 |
摘要
此 RFC 建议更改 zx_task_create_exception_channel
,以允许多达 32 个
调试异常渠道。
设计初衷
Fuchsia 上的调试程序依赖于在作业上创建调试异常通道, 监控进程启动,以便捕获感兴趣的进程, 调试异常渠道通常在 根作业,以便调试程序可以监控所有进程。
当进程启动时,内核会遍历作业层次结构 来通知调试作业异常渠道。此次步行从新的 该进程包含的作业,并且会上层层次结构,直到出现调试作业异常 找到渠道或已到达根作业。
不过,目前的实现方法也存在两个缺点。
- 对于给定的作业,最多只能有一个调试异常渠道,这意味着 大多数调试程序可以监控作业层次结构的任意给定子树。
- 只有第一个找到的调试异常渠道会收到通知,即 子作业上的调试程序阻止父作业上的调试程序观察 进程启动。
利益相关方
教员:cpu@google.com
审核者:brettw@google.com、maniscalco@google.com
已咨询:johngro@google.com
社交化:在 Fuchsia 的《Kernel Evolution Works》(内核演变工作)中讨论了这一想法 群组。
设计
我们提议 Zircon 允许一个作业上有多个调试作业异常通道。
Zircon 中有 5 种例外渠道:
调试作业、作业、调试进程、进程和线程。它们的每一个
最多对相应的对象执行一次。此限制旨在避免
棘手的情况,比如多个异常处理程序针对
ZX_PROP_EXCEPTION_STATE
。
不过,“调试作业”因为它只发出通知
渠道:它能收到的唯一异常类型是 ZX_EXCP_PROCESS_STARTING
其中 ZX_PROP_EXCEPTION_STATE
会被忽略。因此,您可以允许
同时处理一个作业的多个调试异常渠道,而无需担心
不一致性。
在一个作业上创建多个调试作业异常渠道后,
ZX_EXCP_PROCESS_STARTING
事件将依序发送到所有渠道,
允许多个监听器检查进程只有
一个可连接到给定进程的调试程序不会改变,因为“debug”
进程”异常渠道仍然是独有的,除
第一个请求将获得 ZX_ERR_ALREADY_BOUND
。
此外,我们还建议修改
ZX_EXCP_PROCESS_STARTING
事件,以便一个事件可以全部传播
即使子作业中创建了异常渠道也是如此。调试
系统会通知作业层次结构中较低级别的作业异常渠道
优先级高于更高层级的算法在任何给定级别,先前创建的渠道
在后续创建的频道之前收到通知。可以继续
仅在所有异常渠道都收到通知且异常对象时开始
已关闭。
请注意,任何异常消息接收器都可能 只是不关闭异常对象的句柄,从而无限期地启动。 但是,它们不能直接停止进程启动。
实现
系统调用不会有任何 API 或 ABI 更改。当前的行为模式
zx_task_create_exception_channel
将更改为允许最多 N
个频道
而不是在第一个事件发生后返回 ZX_ERR_ALREADY_BOUND
。
性能
性能可能会下降,因为可能会阻塞更多监听器 进程启动。不过,预计不会使用调试异常渠道 或由长时间运行的程序持有。预期 调试器或类似调试工具,因此影响应该微乎其微。
一般来说,调试程序应立即关闭异常句柄 。
安全注意事项
为了避免针对内核的 DoS 攻击, 针对一个作业创建的调试作业异常渠道。上限应该较大 足以允许运行任何合理数量的调试程序,例如 32 个。
测试
我们将向 //zircon/system/utest/debugger
添加新的测试用例以涵盖这方面
功能。
文档
介绍异常处理和
zx_task_create_exception_channel
将
以体现相应更改。
缺点、替代方案和未知问题
替代方案:用户空间的进程委托在根作业上启动
此方法可避免更改内核。而是由用户空间委托
保留根作业调试渠道,并为调试程序提供 FIDL 接口
订阅进程启动受托可以是组件管理器
自行(现在提供fuchsia.kernel.RootJob
)或独立计划。
协议应如以下所示
@discoverable
protocol RootJob {
/// Hanging get pattern
GetProcessStartingEvent() -> (resource struct {
process zx.handle:PROCESS;
continue zx.handle:EVENTPAIR; // dropping this eventpair will propagate
// the event to the next listener.
}) error zx.status;
};
这种方法存在以下问题:
- 它仅适用于根作业。调试程序需要两个逻辑来处理根作业 非根作业
- 在子作业上创建的异常渠道可以阻止事件传播 根。
- 引入 FIDL API,其功能与 系统调用。
替代方案:debug_agent 支持多个客户端
我们还可以让 debug_agent 支持多个客户端,以解决当今的问题, 也就是说,debug_agent 会变为单例。
这些问题包括
- 这会涉及更多工作。
- debug_agent 将成为 Fuchsia 的指定调试程序。其他调试程序 就必须使用 debug_agent,这样会暴露一个大型且不稳定的 界面。