sigwait()在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

我发现以下代码在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 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没有提供“挂起”的定义。看见