简体   繁体   中英

Does sigwait() behave differently in macOS and Linux?

I found the following code works differently in macOS and 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). In other words it looks sigwait() blocks all signals outside its waiting mask during its wait. 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. Therefore it looks in Linux sigwait() does not block the signals outside its waiting mask. Which is the standard behaviour? SUSv3 does not make it clear.

sigwait is clearly not specified to block any signals . If it's doing so on MacOS X, this seems to be a bug.

OS X isn't blocking the extraneous signals, but is instead suspending the process à 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.

Just like a true STOP, OS X keeps the unblockable SIGKILL will at bay until the process resumes. 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.

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. User-defined handlers are invoked, and KILL is respected immediately. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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