title: Multi Threaded Signal Handling in C on Linux
body: <p>Broad Question: What is wrong with my code so that all the signals being generated aren't being caught by the two handler threads?</p>
  
  <p>The unfortunate details for my poor question: I'm supposed to write some code with a main function, 3 generator threads to generate sig1 and sig2 type signals and two signal handling threads. I have tried solving this using the code shown below but I am running into some errors. I tried using sigaction with sigwaitinfo and sigwait to catch signals. But both methods don't seem to work correctly. In the code attached handler1 uses sigaction and sigwaitinfo, handler2 uses sigwait. But I have tried having both handlers use either one and my results are never as I believe they should be. It seems like some signals are never caught. What is wrong with my code so that all the signals aren't being caught? Here is a sample output</p>
  
  <p>Sample Output</p>
  
  <p>signal 1 received</p>
  
  <p>signal 2 received</p>
  
  <p>signal 1 received</p>
  
  <p>signal 2 received</p>
  
  <p>signal 2 received</p>
  
  <p>sigSent1==2,sigSent2==7,sigReceived1==2,sigReceived2==3</p>
  
  <p>A desired output would be</p>
  
  <p>Possible Desired Output</p>
  
  <p>signal 1 received</p>
  
  <p>signal 2 received</p>
  
  <p>signal 1 received</p>
  
  <p>signal 2 received</p>
  
  <p>signal 2 received</p>
  
  <p>signal 1 received</p>
  
  <p>signal 2 received</p>
  
  <p>signal 1 received</p>
  
  <p>signal 2 received</p>
  
  <p>sigSent1==4,sigSent2==5,sigReceived1==4,sigReceived2==5</p>
  
  <p>Sorry if this question is asking a lot but I really have no idea why not all signals are being caught and have been googling around and testing this for like 6 hours today and 3 hours yesterday as well as looking at the man pages...I may be missing something obvious...</p>
  
  <pre><code>#include&lt;semaphore.h&gt;
  #include&lt;stdio.h&gt;
  #include&lt;stdlib.h&gt;
  #include&lt;unistd.h&gt;
  #include&lt;pthread.h&gt;
  #include&lt;time.h&gt;
  #include&lt;signal.h&gt;
  #include&lt;string.h&gt;
  #include&lt;math.h&gt;
  
  /*
     Pre-definitions of functions
   */
  void generator();
  void handler1();
  void handler2();
  void reporter();
  /*
     Global Variables 
   */
  int total_signal_count=0;
  int sentSignal1=0;
  int sentSignal2=0;
  int receivedSignal1=0;
  int receivedSignal2=0;
  sem_t s_lock;
  sem_t r_lock;
  sigset_t set;
  pthread_mutex_t lock;
  pthread_t tid[5];
  /*
     Main function
   */
  int main(int argc, char ** argv)
  {
      int i=0;
      int randomNum=0;
      int error;
      int pid;
      sigset_t mask_all,mask_one,prev_one;
      //Setting up signals 
      //Get Random time
      time_t now;
      time(&amp;now);
      //semaphore is initialized to be global and val 1
      sem_init(&amp;s_lock,0,1);
      sem_init(&amp;r_lock,0,1);
      srand((unsigned) time(&amp;now));
      //Blakc in main thread
      sigemptyset(&amp;set);
      sigaddset(&amp;set,SIGUSR1);
      sigaddset(&amp;set,SIGUSR2);
      pthread_sigmask(SIG_BLOCK,&amp;set,NULL);
      pthread_sigmask(SIG_BLOCK,&amp;set,NULL);
      //Loops until more threads created than 2
      while(i&lt;3)
      {   error=pthread_create(&amp;tid[i],NULL,(void*)generator,NULL);
          if(error!=0)
          {
              printf("failed to create thread\n");
          }
          i++;
      }//end while loop
      while(i&lt;5)
      {
          error=pthread_create(&amp;tid[3],NULL,(void*)handler1,NULL);
          if(error!=0)
          {
              printf("failed to create thread\n");
          }
          error=pthread_create(&amp;tid[4],NULL,(void*)handler2,NULL);
          if(error!=0)
          {
              printf("failed to create thread \n");
          }
          i++;
      }
      //join the threads so main won't return
      i=0;
      int returnVal;
      sleep(10);
      printf("\n sigSent1==%d,sigSent2==%d,sigReceived1==%d,sigReceived2==%d\n",sentSignal1,sentSignal2,receivedSignal1,receivedSignal2);
      while(i&lt;5)//Loops until threads are joined
      {
          //  printf("gonna join %d\n",i);
          pthread_join(tid[i],NULL);
          /*if((returnVal=pthread_join(tid[i],(void**)&amp;returnVal))!=0)
            {
            printf("Error joining thread: %s at %d\n", strerror(returnVal),i);
            }*/
          i++;
      }//end while
      return 0;
  }//end of main function
  /*
     Generator threads
   */
  void generator()
  {
      sleep(1);
      int i=3;
      int randomNum=0;
      int val=0;
      int total_signal_c=9997;
      while(total_signal_c&lt;10000)
      {
          usleep(1);
          //Randomly select to generate SIGUSR1 or SIGUSR2
          //Use pthread_kill(tid,SIGUSR1/SIGUSR2) to send the signal to a thread
          //  printf("total_signal_count%d\n",total_signal_c);
          //Create either a sig1 signal or sig2 signal
          randomNum=rand()%2;
          switch(randomNum)
          {
              case 0:
                  val=pthread_kill(tid[3],SIGUSR1);
                  if(val!=0)
                  {
                      printf("kill fail ==%d\n",val);
                  }
                  sem_wait(&amp;s_lock);
                  //semaphore
                  //mutex
                  sentSignal1++;
                  sem_post(&amp;s_lock);
                  break;
              case 1:
                  val=pthread_kill(tid[4],SIGUSR2);
                  if(val!=0)
                  {
                      printf("kill fail2\n");
                  }
                  sem_wait(&amp;s_lock);
                  sentSignal2++;
                  sem_post(&amp;s_lock);
                  //
                  //
                  break;
          }
  
          i++;
          total_signal_c++;
          //delay for a random time, 0.01 to 0.1 second
      }
  }
  /*
     Handler 1 threads
   */
  void  handler1()
  {
      //Setting up signals
      //  printf("In handler1\n");
      struct sigaction s;
      siginfo_t info;
      sigemptyset(&amp;s.sa_mask);
      //use signal to perma block for handler2
      signal(SIGUSR2,handler1);
      //Add Sigusr1 to set
      sigaddset((&amp;s.sa_mask),SIGUSR1);
      pthread_sigmask(SIG_BLOCK,&amp;s.sa_mask,NULL);
      int val=-1;
      //use signal(), sigaddset(), pthread_sigmask() etc to block and unblock signals as required.
      while(1)
      {   //use sigwaitinfo(); to receive a signal
          val=-1;
          val=sigwaitinfo(&amp;s.sa_mask,&amp;info);
          //if signal received modify the corresponding counter
          if(info.si_signo==SIGUSR1){
              //increment semaphore lock
              sem_wait(&amp;r_lock);
              receivedSignal1++;
              //decrement semaphore lock
              sem_post(&amp;r_lock);
              printf("signal 1 received\n");
          }
          if(val==-1)     
          {
              //      break;
          }
      }
      pthread_exit(NULL);
  }
  /*
     Handler2 threads
   */
  void handler2()
  {
      int sigInfo=0;
      //use signal to perma block for handler2
      signal(SIGUSR1,handler2);
      int val=-1;
      while(1)
      {       //use sigwaitinfo(); to receive a signal
          val=-1;
          val=sigwait(&amp;set,&amp;sigInfo);
          //if signal received modify the corresponding counter
          if(sigInfo==SIGUSR2){
              //increment semaphore lock
              sem_wait(&amp;r_lock);
              receivedSignal2++;
              //decrement semaphore lock
              sem_post(&amp;r_lock);
              printf("signal 2 received\n");
          }       
      }
      pthread_exit(NULL);
  }
  </code></pre>