3

I want to broadcast a signal from one thread to all other threads in a process. The threads receiving that signal should handle the signal in a signal handler. How can I achieve this?


I tried the following code, but it exits by printing User defined signal 1. What's going on?

#include  <stdio.h>
#include  <signal.h>
#include  <sys/types.h>
#include  <pthread.h>

const int NTHREADS = 4;

long  prev_fact, i; 

void  SIGhandler(int);     

void  SIGhandler(int sig)
{
  printf("\nThread %lx Received a SIGUSR1.\n", pthread_self());
}

void* tfunc( void* arg )
{
  printf( "Thread %lx executing...\n", pthread_self() );

  while( 1 )
   ;
}

int main()
{
  int i;
  pthread_t t[NTHREADS];

  for( i = 0; i < NTHREADS; i++ )
   pthread_create( &t[i], NULL, tfunc, NULL );

  for( i = 0; i < NTHREADS; i++ )
   pthread_kill( t[i], SIGUSR1 );

  for( i = 0; i < NTHREADS; ++i) 
   pthread_join(t[i], NULL);

  return 0;
}
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
MetallicPriest
  • 29,191
  • 52
  • 200
  • 356

2 Answers2

4

The portable pthreads way to do this is to loop around all of the threads, executing pthread_kill() for each one. This requires you to maintain a list of all the pthread_t values representing each thread in the process.

On Linux, you can read /proc/self/task to determine the TIDs of every thread in the current process, then use tgkill() to signal them (use the result of getpid() as the tgid parameter to tgkill()).

Note that glibc does not provide a wrapper for tgkill() - you must call it using syscall().

caf
  • 233,326
  • 40
  • 323
  • 462
  • I tried the following code, but it exits by printing User defined signal 1. What's going on? void SIGhandler(int sig) { printf("\nThread %lx Received a SIGUSR1.\n", pthread_self()); } void* tfunc( void* arg ) { printf( "Thread %lx executing...\n", pthread_self() ); while( 1 ) ; } int main() { int i; pthread_t t[NTHREADS]; for( i = 0; i < NTHREADS; i++ ) pthread_create( &t[i], NULL, tfunc, NULL ); for( i = 0; i < NTHREADS; i++ ) pthread_kill( t[i], SIGUSR1 ); for( i = 0; i < NTHREADS; ++i) pthread_join(t[i], NULL); return 0; } – MetallicPriest Jul 05 '11 at 11:53
  • I've added to the code to the answer below. Could you kindly tell me what is going wrong in it? – MetallicPriest Jul 05 '11 at 11:57
  • 2
    @MetallicPriest: You must register your signal handling function using `sigaction()`. You only need to do this once, because signal disposition is shared across all threads. – caf Jul 05 '11 at 12:21
1

The following code works now...

#include  <stdio.h>
#include  <signal.h>
#include  <sys/types.h>
#include  <pthread.h>

const int NTHREADS = 4;

void  SIGhandler(int);     

void  SIGhandler(int sig)
{
     printf("\nThread %lx Received a SIGUSR1.\n", pthread_self());
}

void* tfunc( void* arg )
{
  printf( "Thread %d(%lx) executing...\n", *((unsigned int*)arg), pthread_self() );

  while( 1 )
    ;
}

int main()
{
  int i;
  int tid[NTHREADS];
  pthread_t t[NTHREADS];

  signal(SIGUSR1, SIGhandler);

  for( i = 0; i < NTHREADS; i++ )
  {
    tid[i] = i;
    pthread_create( &t[i], NULL, tfunc, tid+i );
  }

  for( i = 0; i < NTHREADS; i++ )
    pthread_kill( t[i], SIGUSR1 );

  for( i = 0; i < NTHREADS; ++i) 
    pthread_join(t[i], NULL);

  return 0;
}
MetallicPriest
  • 29,191
  • 52
  • 200
  • 356
  • Note that the way you've written this, it doesn't signal the main thread itself (use `pthread_self()` in the main thread to obtain its thread handle). – caf Jul 06 '11 at 04:14