这是 Jochen Sprickerhof、Helmut Grohne 和作者进行的一项调查的故事。这是真正的团队合作,单独工作无法深入了解该问题。他们认为读者会像他们一样觉得有趣,以下是简要内容:
- 阶段 1:不可能发生:11 月下旬,官方 Debian GCC 构建在多个架构上开始失败,构建错误发生在运行测试套件的构建服务器上,但他们认为这不可能发生,因为 GCC 构建在测试套件失败时不应失败,
make
带有-k
参数,且很多 GCC 测试一直失败但包仍能正常构建。 - 阶段 2:我的机器上没发生:在运行 Bookworm 的机器上构建正常,构建守护进程运行 Bookworm 并使用 Sid chroot 作为构建环境,与作者相同,但内核相同。作者和构建守护进程的明显区别是作者使用 sbuild 0.85.0,而构建守护进程使用 0.86.3~bpo12+1,使用 0.86.3~bpo12+1后作者的系统也构建失败,构建守护进程在 11 月下旬某个时候更新到了 bookworm-backports 版本的 sbuild。
- 阶段 3:不应该发生:在 0.85.0 和 0.86.3~bpo12+1 之间有很多 sbuild 版本,查看最近的 sbuild 错误发现 sbuild 0.86.0 破坏了“相当多的包”,使用 0.86.0 构建仍失败,使用 0.85.11 构建成功,通过指定跳过某些语言来缩短构建时间,发现仅跳过 D 语言仍失败且更快,几分钟而非几小时,于是决定提交 bug 报告(无链接)。
- 阶段 4:为什么会发生:发现是某些东西导致构建提前结束,不是 OOM 杀手,内核日志也无有用信息,怀疑是 D 语言测试向某个进程发送信号导致
make
终止,通过bpftrace
跟踪信号发送和接收,发现工作版本的 sbuild 使用dumb-init
,新的使用 perl 中的 init,通过补丁使当前版本的 sbuild 使用dumb-init
并跟踪两个构建,对比发现使用 perl init 时发送了更多 SIGTERM,process.d
的源代码中在单元测试中有sleep
和 SIGINT,可单独研究process.exe
的行为。 - 阶段 5:哦,我明白了:主要问题是为什么使用 perl init 时
process.exe
发送更多 SIGTERM,通过strace
发现 under dumb-init 时kill(-2, SIGTERM)
返回-1 ESRCH (No such process)
,而 underperl-init
时进程存在,kill
的 man 页说明当 pid 小于 -1 时信号发送给进程组,很有用的信息但在 bpftrace 输出中未看到,因为tracepoint:signal:signal_generate
显示信号发送时而非系统调用时,通过跟踪tracepoint:syscalls:sys_enter_kill
可看到负的 PIDs,问题是为什么使用dumb-init
时没有进程组 2。 - 阶段 6:之前怎么能工作:知道
process.exe
向 ID 为 2 的进程组中的每个进程发送 SIGTERM,通过在dumb-init
下启动 shell 观察/proc
中的 PIDs 发现差异,/proc/2/cmdline
显示是 bash 即perl-init
下运行的程序,在构建包时是dpkg-buildpackage
本身,测试意外杀死了自己的进程组,同时说明了测试中-2
的特殊含义及相关代码。感兴趣的读者可查看 bug 报告 #1089007。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。