LWN:对WARN_ON()的警告!

关注了就能看到更多这么棒的文章哦~

Warning about WARN_ON()

By Jonathan Corbet
April 18, 2024
ChatGLM translation
https://lwn.net/Articles/969923/

Linux 内核开发人员,像许多项目的尽职开发者一样,通常会在代码中包含检查条件,期望这些条件永远不会发生,但如果真的发生了,就可以指示出这里出现了严重问题。多年来,开发者一直被鼓励(这是委婉的说法)避免在这种情况下使用断言(assertion)来让系统崩溃(crash),除非确实没有其他选择。然而,最近,内核的 WARN_ON() 这一系列宏(开发者被告知使用的替代方法)也开始受到类似的待遇,不再鼓励使用。

长期以来,对于无法恢复的情况进行判定的一种方式是 BUG_ON() 宏,它包含了对意外条件的判断:

/* 这绝对不会发生,真的,我会撒谎吗? */
BUG_ON(foo_ptr == NULL);

BUG_ON() 调用会直接导致内核崩溃,结果(通常)是机器重新启动。有时候确实没有其他选择,但多年来一直不鼓励使用 BUG_ON() 。因为让机器崩溃会剥夺用户对问题做出反应或保存工作的机会,并可能使问题来源更难以跟踪。尽管如此,内核中大约有 12,000 个 BUG_ON() 的使用位置(不包括 BUILD_BUG_ON() ,它只影响构建过程,因此不需要避免使用)。

相反,开发者被告知使用 WARN_ON(),它将跟踪回溯(traceback)信息记录到内核日志中,但不会导致系统崩溃(至少在理论上是这样,但请继续阅读)。内核的 编码风格文档(coding-style document) 表示:

不要添加新代码来调用 BUG() 的各种变体,包括 BUG()、BUG_ON() 或 VM_BUG_ON() 等。相反,使用 WARN*() 变体,最好是 WARN_ON_ONCE(),并最好带上错误恢复代码。如果没有合理的方式可以至少部分恢复正常,那就不需要恢复代码了。

然而,最近,开发者也被告知尽量避免使用 WARN_ON() 。其中一个原因是,任何可以从用户空间触发的 WARN_ON() 至少可以用来在系统日志中生成垃圾信息,掩盖其他事件,并可能影响系统性能。然而,即使是那些无法以这种方式触发的 WARN_ON() 调用也存在另一个问题。

内核包含一个名为 panic_on_warn 的 sysctl 开关。它正如其名所示:如果设置了此选项,任何 WARN_ON() 调用都将导致系统发生崩溃。实质上,它将 WARN_ON() 调用转换为 BUG_ON() 调用。这个选项会被那些将任何 warning 都视为重要可疑事件的用户设置,他们认为当出现警告时,最好是关闭系统并重新启动。这样的用户包括许多 Android 设备和在云提供商(以及更多地方)运行的主机内核。换句话说,任何一个实际发生的 WARN_ON() 都有可能导致许多机器崩溃。

同一个编码风格文档里 建议开发者,这个结果是 panic_on_warn 用户明确选择的期望结果:

然而,有用户希望使用 panic_on_warn 并不是避免谨慎使用 WARN*() 的有效理由。这是因为,启用 panic_on_warn 的用户明确要求内核在 WARN*() 触发时崩溃,并且这样的用户必须准备好处理系统更有可能崩溃的后果。

然而,对于这种情况下对 WARN_ON() 使用的当前压力并不完全符合这一建议。因此,Alex Elder 最近受到激励,发送了一个补丁,改变了编码风格文档中给出的建议。不再有语言暗示 panic_on_warn 用户得到了他们要求的东西;新的文本如下:

这个选项的存在并不是避免谨慎使用 warning 的有效理由。还有其他选择:``dev_warn*()`` 和 ``pr_warn*()`` 发出 warning,但  会导致内核崩溃。如果你想要阻止这样的 panic,就使用这些函数。

Christoph Hellwig 迅速 表示,这种改变是“更错误的”:如果设置了 panic_on_warn,你就得承担后果。Laurent Pinchart 指出,这里所建议的替代方案并不能起到同等作用;它们更容易被忽略,因此更加不容易引起开发者注意到这些 warning 从而来解决问题。然而,Greg Kroah-Hartman 对这一改变感到高兴。他表示,应该避免添加新的 WARN_ON() 调用。

总而言之:多年来, BUG_ON() 被视为非常具有破坏性,以至于开发者被简单地告知 不要使用它. WARN_ON() 宏已经取代了它;但在设置了 panic_on_warn 的情况下, WARN_ON() 调用的最终结果实质上是相同的。因此,自然而然地,现在多数情况下也不鼓励使用 WARN_ON() 。

是否会合入这个建议的文档改动还尚不清楚;内核的文档维护者就很庆幸没有被任命为内核编码风格的裁决者,一直都坚持不在缺乏明确共识的情况下进行编码风格的更改。目前尚不清楚对这一变更是否存在共识。尽管如此,不论是否更改,开发者将继续被鼓励使用诸如 pr_warn() 这样的记录函数,而不是 WARN_ON() — 直到某人不可避免地添加一个 panic_on_pr_warn sysctl 开关之后也许整个过程可以重新开始。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

d733042dd4289b7bd3e7588854ed6824.jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值