Joe
Joe

Reputation: 223

Exiting a thread that contains a blocking statement in c

I made a program with multiple processes, each with a number of threads. I want to stop the program using ctrl-c, and decided to use an interrupt handler. To do this I used the signal() function to set a flag when ctrl-c is pressed. Most of the threads contain loops that don't have a blocking statement in them, and just run while the flag is not set. When the flag is set, the loop ends and pthread_exit() is called. Some of the threads contain a blocking statement, and might not get to the point where the flag change is noticed and the loop can end.

In the example below, this would result in a memory leak (malloc() without a free() ) and a process that was not ended properly.

I checked many Q&A's, but could not find a proper solution. Any help would be greatly appreciated!

I added an example below (pseudo-code):

int flag = 0;

int main(void)
{
    // when (CTRL-C) is pressed, execute the interrupt handler
    signal(SIGINT, interrupt_handler_STATSERVER);

    // -- THREAD1: continuously receive packets from the data server
    pthread_t receivePackets_thread;
    int rc = pthread_create(&receivePackets_thread, NULL,(void*) receiveFromDataServer, NULL);
    if (rc)
    {
        printf("ERROR; return code from pthread_create() is %d\n", rc);
        exit(-1);
    }
}


void* receiveFromDataServer(void)
{
    while(flag == 0)
    {
        //every loop, allocate memory for a packet
        packet = (ProcessedPacket*) malloc(sizeof(ProcessedPacket));
        if(packet == NULL)
        {
            // ERROR: mem allocation error
        }
        else
        {
            // wait for a connection
            //*** THE BLOCKING STATEMENT IS HERE ***
        }       
    }

    pthread_exit(NULL);
}

void interrupt_handler_STATSERVER(int signum)
{
    printf("STAT SERVER INTERRUPT!\n");
    flag = 1;   
}`

Upvotes: 1

Views: 120

Answers (1)

xaxxon
xaxxon

Reputation: 19761

Make sure to mask off SIGINT on all your child threads, as signal delivery is to a single, arbitrary thread without the signal masked. This guarantees your "management thread" will get the ctrl-c. Then, use pthread_kill from your management thread to send signals to your other threads using an unmasked signal. This will interrupt your blocking calls and allow you to test flags and such.

Read this: http://man7.org/linux/man-pages/man7/signal.7.html

especially the section titled: Signal mask and pending signals

Use pthread_sigmask to examine and change your thread's signal mask.

Upvotes: 1

Related Questions