Question

I have recently started programming using signals. I used them in my multithreaded server code in C. Here is the part of code pertinent to signals, but it doesn't work as it should do:

the signal Handler:

void* Ctrl_C_handler(void *arg)
{
int *sock_fd_ptr = (int*)arg;
sigset_t set;
int err, sig;

err = sigemptyset(&set);                // Clear the signals holder set
if(err) perror("sigemptyset(&set)");

err = sigaddset(&set, SIGINT);          // Add the SIGINT: Ctrl+C
if(err) perror("siaddset(&set, SIGINT)");

err = pthread_sigmask(SIG_UNBLOCK, &set, NULL); // Set mask as to unblock SIGINT
if(err) perror("pthread_sigmask(SIG_SETMASK, &set, NULL)");

printf("Signal handler active:\n");
while(1)        // Ctrl+C
{
    err = sigwait(&set, &sig);          // Wait for signal to occur
    if(err)
    {
        perror("sigwait(&set, &sig)");
        printf("Error handling the signal, SigHandlerThread exiting..\n");
        break;
    }

    if(sig == SIGINT)
    {
        printf("Ctrl+C detected by server !!\n");
        printf("No more connections will be accepted!!");
        if(*sock_fd_ptr > 0)
        {
            close(*sock_fd_ptr);
            *sock_fd_ptr = -1;
            break;
        }
    }   
}
return NULL;

}

Inside Main():

/*********** Signal Handling *************/

sigset_t set;                       // declare a set to hold the signals 
err = sigfillset(&set);             // Fill the set with all the signals
if(err) perror("sigfillset(&set)");

err = sigthreadmask(SIG_BLOCK, &set, NULL);  // Block/Mask the signals in the set
if(err) perror("sigthreadmask(SIG_BLOCK, &set, NULL)");

err = pthread_create(&sig_handler_tid, NULL, Ctrl_C_handler, (void *)&sock_fd);
                                    // Create a thread for handling signals
if(err) perror("pthread_create");

I read this method here. I tried sending kill -s SIGINT <pid of my program> from different terminal window, but the program exits.

Was it helpful?

Solution

When the SIGINT is sent to your process, it is delivered to the only thread that has it unblocked, your Ctrl_C_handler thread. Signal delivery means taking whatever action is associated with the signal, and the default action for SIGINT is, as you know, process termination.

But why doesn't sigwait() calmly intercept the signal, as you intend?

sigwait() is designed to remove a signal from a mask of pending signals — that is, generated signals whose delivery is suspended (SIG_BLOCKed) — without the usual asynchronous drama of signal delivery.

So, don't SIG_UNBLOCK SIGINT in your thread. Instead, keep it blocked and the code will work as you intend. If you scrutinize the reference you provided, you'll see that that sample code blocks all signals before calling sigwait().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top