Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

master / worker threads and signal handling

I am writing a program, with a master thread and some worker threads, and I would like to get the signal handling right. My problem is the following :

Master thread starts and do all allocation

Master thread sets a SIGINT signal handler

Master threads start worker threads. worker threads don't need special cleanup, however they can be sleeping on system call or semaphore.

When SIGINT is received, my understanding is that only one thread receives it. So if thread are sleeping on system call or semaphore, they wont be waked up, and I won't be able to pthread_join my worker threads and do all the necessary cleanup in my master thread.

Can the following signal handler resolve my problem ?

void term(int sig)
{
    g_do_cleanup = 1;
    pthread_kill(worker_1_id, some_other_signal);
    ...
    pthread_kill(worker_2_id, some_other_signal);
}

What I expect is that upon receiving SIGINT, all thread will be signaled with another signal, get out of their blocking call, see the g_do_cleanup flag and gracefully exit.

Any comment or link on how to do this properly is welcome.

Edit : I am NOT looking for a way to wakeup multiple thread waiting on a particular condition, so I don't think the pthread_cond_signal approach is what I am looking for. What I want is :

  • Find a way that all thread that are blocked on a blocking call returns from these calls.
  • Or kill all threads except for the main one.
like image 426
shodanex Avatar asked May 27 '09 14:05

shodanex


2 Answers

This is what I usually do in the main app thread:


/* before starting other threads */
sigset_t sigs;
sigemptyset( &sigs );
sigaddset( &sigs, SIGTERM );
sigaddset( &sigs, SIGINT );
/* add other signals to handle */
if ( pthread_sigmask( SIG_BLOCK, &sigs, 0 )) { /* handle error */ }
/* can start threads now */
...
/* in the main event loop */
siginfo_t info;
if ( sigwaitinfo( &sigs, &info ) == -1 ) { /* handle error */ }
switch( info.si_signo )
{
  case SIGTERM:
  case SIGINT: /* raise shutdown event */ break;
  default: /* other actions - log rotation, etc. */
}
...

This way signals become regular application events - no special signal context restrictions, etc. Waiting could also be done with a timeout via sigtimedwait, though BSD derivatives don't support it.

like image 183
Nikolai Fetissov Avatar answered Oct 24 '22 10:10

Nikolai Fetissov


It sounds to me like what you want is a pthread condition variable, so that you can wake any number of multiple threads by singalling one "event" from your master thread.

See the man pages for PTHREAD_COND_DESTROY and PTHREAD_COND_BROADCAST for more information.

like image 31
T.E.D. Avatar answered Oct 24 '22 11:10

T.E.D.