Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to block all SIGNALS in thread WITHOUT using SIGWAIT?

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

like image 571
Lynton Grice Avatar asked Nov 11 '11 12:11

Lynton Grice


1 Answers

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.

like image 126
nos Avatar answered Nov 01 '22 00:11

nos