另一种可能性是,他的函数仅在一个应用程序(或一个应用程序的一部分)中使用,该应用程序已经做了一些事情来确保调用不会被信号中断。如果您不打算对信号做任何重要的事情,那么您不必对它们做出响应,并且将它们全部屏蔽掉可能是有意义的,而不是将每个阻塞系统调用包装在 EINTR 重试中。当然除了会杀死你的那些,所以如果你通过退出来处理它,那么 SIGKILL 和经常 SIGPIPE 以及 SIGSEGV 和类似的致命错误在任何情况下都不会传递到正确的用户空间应用程序。
无论如何,如果他所说的只是安全性,那么他很可能不必重试close
。如果关闭 EIO 失败,那么他将无法重试,这将是永久失败。因此,成功的程序的正确性是不必要的close
。很可能他的程序的正确性也没有必要close
在 EINTR 上重试。
通常你希望你的程序尽最大努力成功,这意味着在 EINTR 上重试。但这是与安全性不同的问题。如果您的程序被设计为使某些功能因任何原因而失败不是安全漏洞,那么特别是它恰好因 EINTR 而不是由于永久原因而失败的事实就不是缺陷。众所周知,DJB 相当固执己见,所以如果他证明了他不需要重试的某种理由,因此我不会感到惊讶,因此即使这样做会让他的程序成功在当前可能失败的某些情况下刷新手柄(例如kill
在关键时刻由用户明确发送无害信号)。
编辑:在我看来,在某些条件下重试 EINTR 本身可能是一个安全漏洞。它为该部分代码引入了一种新行为:它可以无限循环以响应信号泛滥,以前它会尝试close
然后返回。我不确定这是否会导致 qmail 出现任何问题(毕竟,close
它本身并不能保证它会在多长时间内返回)。但是,如果在一次尝试后放弃确实使代码更易于分析,那么它可能是一个明智的举措。或不。
您可能认为重试可以防止 DoS 缺陷,其中信号会导致虚假故障。但是重试允许另一个(更困难的)DoS 缺陷,其中信号泛滥会导致无限期的停顿。就二进制“这个应用程序可以 DoSed 吗?”而言,这是 DJB 在编写 qmail 和 djbdns 时感兴趣的绝对安全问题,没有区别。如果某件事可以发生一次,那么通常这意味着它可以发生多次。