禁用 signal 函数
15.4 ID_forbidSignalFunction
signal 函数具有一定的局限性,且各平台实现差异较大。
示例:
#include <signal.h>
void handler(int signum) { // #1
signal(signum, handler); // #2, non-compliant, race condition
....
}
设例中 handler 是某种信号的处理函数。在某些平台上,signal 指定的函数只能被执行一次,所以需要在 handler 中再次调用 signal 指定处理函数,但如果程序在运行到 #1 和 #2 之间时收到同样的信号,会执行不符合预期的默认处理函数,这是一种竞态条件;而在另一些平台上,signal 指定的函数会一直有效,handler 再次调用 signal 是多余的。
与 signal 函数相似的 sigaction 函数不存在这些问题,也可提供更多的功能,但要注意该函数尚未在语言标准中定义。
如果条件允许,也可以使用 sigwait、sigwaitinfo 等函数同步地处理信号,如:
sigset_t ss;
sigemptyset(&ss);
sigaddset(&ss, SIGINT);
sigprocmask(SIG_BLOCK, &ss, NULL);
while (1) {
int signum = sigwaitinfo(&ss, NULL); // Wait for signals
if (signum == SIGINT) {
.... // Handle the signal
}
}
例中 sigwaitinfo 函数在没有信号到达时会阻塞,否则返回相应的信号值,这样可以同步地处理信号,避免了异步信号处理需要面对的数据竞争等问题,也使代码具有更清晰的静态结构。
相关
依据
ISO/IEC 9899:1999 7.14.1.1(3)-implementation
ISO/IEC 9899:2011 7.14.1.1(3)-implementation
ISO/IEC 9899:2011 7.14.1.1(7)-undefined
参考
MISRA C 2012 21.5
MISRA C++ 2008 18-7-1
SEI CERT SIG01-C
SEI CERT SIG34-C