我只是想知道是否可以在信号处理程序中调用非异步安全函数。
引用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);我也在无限循环中调用printf(),在main()中,我只运行主线程。
问题是,对于这个简单的例子,当处理程序中断了printf() 的执行并且调用了一个不安全的函数时,我没有看到任何不好的事情发生。 AFAK,printf()将获得一个控制台锁,并有一个内部缓冲区来执行缓冲的I/O,但是在这个例子中,它的状态是一致性。虽然crypt()返回静态分配的字符串,但它不与其他函数或线程共享。
我是不是误会了什么?我希望有人澄清一下,总是不安全的,如果一个信号处理程序中断了主程序中不安全函数的执行,并且它本身也调用了一个不安全的函数,或者在某些情况下这样做是安全的(例如上面的简单例子)?
发布于 2015-08-24 18:00:46
如果信号中断了主程序中的任何异步不安全函数,则调用信号处理程序中的任何异步不安全函数是不安全的。异步-不安全的函数不需要彼此有任何关系--结果是未定义的。
因此,在信号处理程序中安全调用异步不安全函数的唯一方法是确保在调用aysnc不安全函数时永远不会发生信号。一种方法是将对任何异步不安全函数的每个调用都用适当的σ块/Sigset掩码调用包装,以确保在不安全的函数运行时不会传递信号。另一种方法是在调用异步不安全函数时设置/清除sigatomic标志,并让信号处理程序在尝试调用异步不安全函数之前检查该标志。
使用同步信号(比如SIGFPE和SIGSEGV),情况可能会好一些,因为在那里,您可以确保异步不安全的函数不会触发这些信号,并且您不允许(或不关心)使用kill异步发送这些信号。但是,这需要一些注意--如果您有一个SIGSEGV的信号处理程序来捕获写入保护内存,那么您需要确保永远不会将受写保护的内存传递给异步不安全的函数,因为它可能会触发处理程序。
https://stackoverflow.com/questions/32185822
复制相似问题