How to block all SIGNALS in thread WITHOUT using SIGWAIT?

14,279

With s = pthread_sigmask(SIG_BLOCK, &set, NULL); , you're not blocking anything.

Use:

sigfillset(&set);
sets = pthread_sigmask(SIG_SETMASK, &set, NULL);

If you want to block every signal, or explicitly add the signals you want to block to the set if you're using SIG_BLOCK.

After you've created the threads, you need to restore the signal mask, otherwise no threads will catch any signal.

However, looking at your previous question, it might be that the thread catching the signal doesn't handle being interrupted. That is, if you're blocked doing a syscall, and a signal arrives, that syscall gets aborted. Some operating systems defaults to automatically call the system call again, some returns an error and sets errno to EINTR, which the application must handle - and bad things might happen if that's not handled.

Instead, install your signal handlers with sigaction() instead of signal() , and set the SA_RESTART flag, which will cause system calls to automatically restart in case it got aborted by a signal.

Share:
14,279
Lynton Grice
Author by

Lynton Grice

Updated on June 14, 2022

Comments

  • Lynton Grice
    Lynton Grice almost 2 years

    I have a main application that spawns a seperate thread to process messages off a queue. I have an issue on AIX when I hit CTRL-C as it seems to make some "connection handles" in the thread become invalid. I do have a shutdown hook in the main program catching the SIGINT but on AIX it seems to somehow send a signal to the thread as well...although that is not really possible from what I hear...

    Essentially I would like to know if I want the MAIN application to handle ALL signals I am interested in and have the thread/s NEVER handle any signals...is that "good practice"?

    If so how can I NOT use "sigwait" in the thread...in fact I do not want any "signal code" in the thread/s...they must simply not receive any signals at all.

    I have emptied out all the signals:

    sigemptyset(&set);
    

    And have set the SIG_BLOCK

    s = pthread_sigmask(SIG_BLOCK, &set, NULL);
    

    So here is a dummy test programe:

    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <signal.h>
    #include <errno.h>
    
    #define handle_error_en(en, msg) do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
    
    static void * threadMainLoop(){
        //Here I do not want the thread to use "sigwait"....
        while(running == TRUE){
          //do some thread work and never have any signals come in
        }
    }
    
    void shutdownHook(int sig){
        printf("\nCtrl-C pressed....shutdown hook in main...\n");
    }
    
    void signalErrorHandler(int signum){
        printf("\nSignal error handler in main...\n");
    }
    
    int main(int argc, char *argv[]){
        pthread_t thread;
        sigset_t set;
        int s;
    
        //Catch the following signals in the MAIN thread
        (void) signal(SIGINT, shutdownHook);
        (void) signal(SIGSEGV, signalErrorHandler);
        (void) signal(SIGBUS, signalErrorHandler);
        (void) signal(SIGILL, signalErrorHandler);
        (void) signal(SIGTERM, signalErrorHandler);
        (void) signal(SIGABRT, signalErrorHandler);
    
        sigemptyset(&set); //BLOCK all signals
    
        s = pthread_sigmask(SIG_BLOCK, &set, NULL);
        if (s != 0)
            handle_error_en(s, "pthread_sigmask");
    
        s = pthread_create(&thread, NULL, &threadMainLoop, (void *) NULL);
        if (s != 0)
            handle_error_en(s, "pthread_create");  
    
        pause();
    }
    

    If I just create a thread and have, for example, the SIGINT signal handler in the MAIN thread but do NOT has the SIG_BLOCK set for the thread and the user hits CTRL-C....does the thread get affected at all even though the signal handler in the main thread runs? That seems to be what I am seeing on AIX ;-(

    Thanks for the help, much appreciated

    Lynton

  • Lynton Grice
    Lynton Grice over 12 years
    Hi there, but it I set "s = pthread_sigmask(SIG_BLOCK, &set, NULL);" and test with CTRL-C that thread does not receive the signal? That means it is blocking it? If I add "sigaddset(&set, SIGINT);" then the thread receives the signal. Forgive me if I am wrong here...I am still learning..;-) Thanks for the help ;-)
  • nos
    nos over 12 years
    Updated the answer a bit.. The signal mask is the signals that cannot be raised. So if you do sigaddset(&set, SIGINT); pthread_sigmask(SIG_BLOCK, &set, NULL); , SIGINT will be set in the singnal mask, and that means the thread will not receive it. If you create a new thread, that thread inherits the signal mask from the thread that created it.
  • R.. GitHub STOP HELPING ICE
    R.. GitHub STOP HELPING ICE over 12 years
    Note that if you want a new thread to start with signals masked (usually necessary to avoid nasty race conditions) you need to block the signals before calling pthread_create and then restore the old signal mask in the original thread after pthread_create returns.
  • chill
    chill over 12 years
    @LyntonGrice, when you block the signal and it is sent to he thread, the signal remains pending to the thread. When you later unblock the thread, the signal will be delivered. If you don't want the signal delivered, you have to ignore it, not block it.