【发布时间】:2015-08-24 15:14:46
【问题描述】:
我只是想知道是否可以在信号处理程序中调用非异步安全函数。
引自 Linux 手册页信号(7):
如果信号中断了不安全函数的执行,并且处理程序调用了不安全函数,则程序的行为是未定义。
和TLPI:
SUSv3 指出表 21-1(异步安全函数列表)中未列出的所有函数都被认为对信号不安全,但指出只有在调用信号处理程序时函数才不安全 中断不安全函数的执行,并且处理程序本身也调用不安全函数。
我对上述引用的解释是只有在信号处理程序没有中断非异步安全函数的情况下,才可以安全地从信号处理程序调用非异步安全函数 。
例如,我为 SIGINT 安装了一个处理程序,它调用了一个假定为 crypt(3) 的不安全函数,它是不可重入的,即不安全的。
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = handler;
sigaction(SIGINT, &sa, NULL);
我还在main()中无限循环调用printf(),我只有主线程在运行。
问题是这个简单的例子,当处理程序中断 printf() 的执行并调用不安全的函数时,我没有看到任何不好的事情发生。 AFAK,printf() 将获取控制台锁并有一个内部缓冲区来执行缓冲 I/O,但在此示例中其状态是一致。而且虽然crypt()返回的是一个静态分配的字符串,但它并不与其他函数或线程共享。
我是不是误会了什么?我希望有人澄清一下,让信号处理程序中断主程序中不安全函数的执行并且本身也调用不安全函数或者在某些情况下这样做是安全的,这是否总是不安全 (例如上面的简单示例)?
【问题讨论】:
-
不安全并不意味着你会总是被烧毁。
-
只要标准说不安全,就是不安全。我们不知道是否会一直如此。 “不安全”的意思是“可能会发生坏事”,而不是“……会发生”。
-
你在编写什么样的应用程序?它是关键的嵌入式软件还是无用的游戏演示?
-
@BasileStarynkevitch 实际上,我正在编写一个实用函数,例如 gdb 中的
backtrace命令,它将打印调用堆栈,并将从 SIGSEGV 处理程序中调用。这是一个操作系统课程项目。 -
这个相关的问题可能很有趣stackoverflow.com/questions/14421951/…。
标签: c linux signals async-safe