tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: sigwait() and SIGSEGV



OK, the problem seems to be:

If all threads block all signals and then only one thread calls sigwait(), 
then the thread waiting on sigwait() will only get those signals that are sent 
to the whole process, not individual threads.

So if one thread calls 'pthread_kill(pthread_self(), SIGUSR1)' that signal 
will be pending for this particular thread and will not be delivered to the 
thread waiting on sigwait().

Is this the correct Posix behavior?

This is what NetBSD man page for sigwait() says:

        ...
        If several threads are waiting for a given signal, exactly one of them
        returns from the signal wait when the signal is generated.

The above does not seem to happen. Any ideas?

I've attached a simple C program that illustrates this.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <signal.h>

/* Each worker thread runs this function */
void *run_thread(void *arg)
{
        int tid = *((int *)(arg));
        sigset_t sigset;

        printf("tid=%d, before pthread_kill()\n");
        sigpending(&sigset);
        if(sigismember(&sigset, SIGUSR1))
                printf("tid=%d, SIGUSR1 is pending\n", tid);
        else
                printf("tid=%d, SIGUSR1 is not pending\n", tid);

        while(1)
        {
                /* Send a signal to itself */
                if(pthread_kill(pthread_self(), SIGUSR1) != 0)
                        printf("pthread_kill error\n");

                printf("tid=%d, thread running...\n", tid);

                printf("tid=%d, after pthread_kill()\n");
                sigpending(&sigset);
                if(sigismember(&sigset, SIGUSR1))
                        printf("tid=%d, SIGUSR1 is pending\n", tid);
                else
                        printf("tid=%d, SIGUSR1 is not pending\n", tid);

                sleep(8);
        }
}

/* Only one signal handling thread runs this function */
void *sig_thread(void *arg)
{
        sigset_t *sigset = (sigset_t *)arg;
        int signum;

        while(1)
        {
                sigwait(sigset, &signum);
                switch(signum)
                {
                        case SIGUSR1:
                                printf("SIGUSR1\n");
                        break;
                        case SIGSEGV:
                                printf("SIGSEGV\n");
                                exit(1);
                        break;
                        default:
                                printf("Got signal %d, exiting\n", signum);
                                exit(1);
                }
        }
}

int main(void)
{
        pthread_t stid;                 /* signal thread id */
        pthread_t tid0, tid1;   /* other thread id */
        int int_id0 = 0;                /* thread integer ids */
        int int_id1 = 1;
        
        sigset_t sigset;

        setbuf(stdout, NULL);

        sigfillset(&sigset);
        pthread_sigmask(SIG_SETMASK, &sigset, NULL);

        printf("Starting signal handling thread\n");
        pthread_create(&stid, NULL, &sig_thread, &sigset);
        
        printf("Starting 2 worker threads\n");
        pthread_create(&tid0, NULL, &run_thread, &int_id0);
        pthread_create(&tid1, NULL, &run_thread, &int_id1);
        
        pthread_exit(0);
}


Home | Main Index | Thread Index | Old Index