0xF1
0xF1

Reputation: 6116

Why is this code not working as expected?

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.

Upvotes: 2

Views: 334

Answers (1)

pilcrow
pilcrow

Reputation: 58524

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().

Upvotes: 2

Related Questions