简体   繁体   English

sigwait() 在 macOS 和 Linux 中的行为是否不同?

[英]Does sigwait() behave differently in macOS and Linux?

I found the following code works differently in macOS and Linux:我发现以下代码在 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 );
    }
}

When run on macOS and a SIGINT is sent to the process, its handler is executed only after a SIGHUP is sent (thus causing sigwait() to return).当在 macOS 上运行并将 SIGINT 发送到进程时,仅在发送 SIGHUP 后才执行其处理程序(从而导致 sigwait() 返回)。 In other words it looks sigwait() blocks all signals outside its waiting mask during its wait.换句话说,它看起来 sigwait() 在等待期间阻塞了其等待掩码之外的所有信号。 When the same program is run on Linux, SIGINT is delivered, that is the handler is run, as soon as a SIGINT is sent to the process.当相同的程序在 Linux 上运行时,SIGINT 被传递,即处理器运行,只要一个 SIGINT 被发送到进程。 Therefore it looks in Linux sigwait() does not block the signals outside its waiting mask.因此,它在 Linux 中看起来 sigwait() 不会阻止其等待掩码之外的信号。 Which is the standard behaviour?哪个是标准行为? SUSv3 does not make it clear. SUSv3 没有明确说明。

sigwait is clearly not specified to block any signals . sigwait 显然没有指定阻止任何信号 If it's doing so on MacOS X, this seems to be a bug.如果它在 MacOS X 上这样做,这似乎是一个错误。

OS X isn't blocking the extraneous signals, but is instead suspending the process à la SIGSTOP. OS X 不会阻止无关信号,而是暂停进程 à la SIGSTOP。

I find this a reasonable implementation of the specification (IEEE Std 1003.1-2017), which requires that sigwait(set, &s) suspend the calling thread until at least one signal in set becomes pending.我发现这是规范(IEEE Std 1003.1-2017) 的合理实现,它要求sigwait(set, &s)挂起调用线程,直到set中的至少一个信号变为挂起。

Just like a true STOP, OS X keeps the unblockable SIGKILL will at bay until the process resumes.就像真正的 STOP 一样,OS X 会阻止无法阻止的 SIGKILL 直到进程恢复。 ps can see a difference between STOP and sigwait , and of course the process resumption is different for each (CONT vs. set ), but they're essentially the same process state. ps可以看到 STOP 和sigwait之间的差异,当然每个进程恢复的过程都不同(CONT 与set ),但它们本质上是相同的进程状态。

Linux, on the other hand, seems to me to pretend that sigwait is interruptible, and further that user-defined actions were installed with SA_RESTART.另一方面,在我看来,Linux 认为sigwait是可中断的,而且用户定义的操作是通过 SA_RESTART 安装的。 User-defined handlers are invoked, and KILL is respected immediately.调用用户定义的处理程序,并立即遵守 KILL。 This behavior is, in my opinion, much more useful, but not to spec — the thread is simply not suspended if it can execute a user-defined signal handler.在我看来,这种行为更有用,但不符合规范——如果线程可以执行用户定义的信号处理程序,它就不会挂起。

Of course, this circumstance is a bit contrived, as sigwait is really designed with multithreaded programs in mind.当然,这种情况有点做作,因为sigwait确实是为多线程程序设计的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM