sigwait()在macOS和Linux中的行为是否不同?
我发现以下代码在macOS和Linux中的工作方式不同:sigwait()在macOS和Linux中的行为是否不同?,c,macos,linux-kernel,signals,sus,C,Macos,Linux Kernel,Signals,Sus,我发现以下代码在macOS和Linux中的工作方式不同: #include <signal.h> #include <unistd.h> #include <stdio.h> void catcher( int sig ) { printf( "Signal catcher called for signal %d\n", sig ); } int main( int argc, char *argv[] ) { struct sigac
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
void catcher( int sig ) {
printf( "Signal catcher called for signal %d\n", sig );
}
int main( int argc, char *argv[] )
{
struct sigaction sigact;
sigset_t waitset;
int sig;
int result = 0;
sigemptyset( &sigact.sa_mask );
sigact.sa_flags = 0;
sigact.sa_handler = catcher;
sigaction( SIGINT, &sigact, NULL );
sigemptyset( &waitset );
sigaddset( &waitset, SIGHUP);
result = sigwait(&waitset, &sig) ;
if(result == 0)
{
printf( "sigwait() returned for signal %d\n", sig );
}
}
#包括
#包括
#包括
空隙捕捉器(内部信号){
printf(“为信号%d\n调用的信号捕捉器”,sig);
}
int main(int argc,char*argv[])
{
struct-sigaction-sigact;
sigset_t waitset;
int-sig;
int结果=0;
sigemptyset(&sigact.sa_mask);
sigact.sa_标志=0;
sigact.sa_handler=catcher;
sigaction(SIGINT,&sigact,NULL);
sigemptyset(&waitset);
sigaddset(&waitset,SIGHUP);
结果=sigwait(&waitset,&sig);
如果(结果==0)
{
printf(“为信号%d\n返回的sigwait(),sig”);
}
}
在macOS上运行并向进程发送SIGINT时,其处理程序仅在发送SIGHUP后执行(从而导致sigwait()返回)。换句话说,在等待过程中,sigwait()会阻止等待掩码之外的所有信号。当同一个程序在Linux上运行时,SIGINT被传递,即处理程序在SIGINT被发送到进程后立即运行。因此,看起来Linux中的sigwait()不会阻止等待掩码之外的信号。
哪一种是标准行为?SUSv3没有明确说明这一点
sigwait
是。如果它在MacOS X上这样做,这似乎是一个bug。OS X没有阻止无关信号,而是暂停进程
我发现这是(IEEE Std 1003.1-2017)的合理实现,它要求sigwait(set,&s)
暂停调用线程,直到set中至少有一个信号变为挂起
就像真正的停止一样,OSX将阻止不可阻止的SIGKILL,直到进程恢复ps
可以看到STOP和sigwait
之间的区别,当然每个进程的恢复都不同(CONT和set),但它们本质上是相同的进程状态
另一方面,在我看来,Linux似乎假装sigwait
是可中断的,而且用户定义的操作是通过sau重启安装的。调用用户定义的处理程序,立即执行KILL。在我看来,这种行为更有用,但不符合规范——如果线程可以执行用户定义的信号处理程序,它就不会被挂起
当然,这种情况有点做作,因为
sigwait
实际上是为多线程程序设计的。这也是我的印象。感谢对这个问题的评论,如果你没有阻止你正在等待的信号,那么这个行为看起来实际上是未定义的。所以从理论上讲,你有可能打到这个UB。但不需要阻止您不等待的信号。@R..,经过反思和测试,我认为OSX并没有阻止,而是挂起。“看我的答案来解释原因。@pilcrow:这不是它的工作原理。”。不允许EINTR并不意味着函数执行时信号被延迟。只是在信号处理程序返回后它继续运行。这都在XSH的信号部分中指定,在单独的函数之前。我可以要求您在调用sigwait
之前包含和SIG_阻止该SIGINT吗?(两者都不会从你所识别的陌生感中减去。)显然signal.h
被包括在内(这行刚刚从副本中滑出,否则它就不会编译了)。添加SIGINT块只需在macOS中按预期工作即可。也就是说,SIGINT被阻止了,在SIGHUP之后,程序会定期退出。对不起,我打错了后面的部分-我是说SIG_阻止了SIGHUP。对非阻塞信号使用sigwait
是明确未定义的。我不确定是否理解:SUS说“set定义的信号应该在调用sigwait()时被阻塞;否则,行为是未定义的。”这里的问题是传递给sigwait()的信号不在集合中。这不是它的工作方式。不允许EINTR并不意味着函数执行时信号被延迟。只是在信号处理程序返回后它继续运行。这都是在XSH的signals部分中指定的,在单个函数之前。如果线程可以执行用户定义的信号处理程序,那么它就不会挂起。不幸的是,POSIX没有提供“挂起”的定义。看见