title: How to terminate threads cleanly in C?
body: <p>I am trying to write a multithreaded application in C for the Raspberry Pi in raspbian environment (UNIX system).</p>
  
  <p>Apart from the main thread three other threads are created and do the following:</p>
  
  <ol>
  <li>the first looks at the output of a PIR sensor and if movement is detected it takes a picture. The thread function is <code>task1()</code>;</li>
  <li>the second uses <code>sigwait</code> and <code>alarm()</code> to measure the temperature every given seconds. The thread function is <code>task2()</code></li>
  <li>The third thread checks if a new picture is taken and if so it does some other stuff. The synchronization with the first thread is done with a global flag, a mutex and with <code>pthread_cond_wait</code>. The thread function is <code>task3()</code>.</li>
  </ol>
  
  <p>All the thread functions have an infinite loop. The execution of the program seems good.</p>
  
  <p>The main thread call the function <code>pause()</code> and then <code>pthread_cancel()</code> to exit cleanly from each thread (lowering the pins).
  At first I did not use the signal handler and the process quit without calling the exiting thread functions registered with the function <code>pthread_cleanup_push</code>. This because <code>pause()</code> returns only if the handler returns. That is why I added my signal handler which returns.</p>
  
  <p>In this way the <code>pthread_cancel</code> are called correctly and also the exiting thread functions are called correctly (the output is printed) but the process keeps running even with pressing CTRL-C or calling kill from another terminal window. </p>
  
  <p>I think I messed up with the masks so that the signal generated by <code>pthread_cancel</code> (if any) has no effect.</p>
  
  <p>Apart from this I have read that in general it is bad practice using <code>pthread_cancel</code> so my question is: </p>
  
  <p><strong>what is the best way to exit cleanly from each thread (especially in my case)? Shall I use another global flag? With mutex or read-write lock? Should I set it from the main thread or handler?</strong></p>
  
  <p>Any suggestion will be appreciated.</p>
  
  <p>EDIT: If instead of calling <code>pthread_cancel</code> I use a global flag for the infinite loops, how would you set the condition in <code>task3()</code>?</p>
  
  <p>NOTE: the code is incomplete for the sake of brevity. I tried to emphasize the logic. If needed I will add all the code.</p>
  
  <pre><code>#include&lt;wiringPi.h&gt;  
  #include&lt;stdlib.h&gt;
  #include&lt;stdio.h&gt;
  #include&lt;signal.h&gt;
  #include&lt;stdint.h&gt;
  #include&lt;pthread.h&gt;
  
  g_new_pic_flag=FALSE;
  pthread_cond_t g_new_pic_cond = PTHREAD_COND_INITIALIZER;
  pthread_mutex_t g_new_pic_m = PTHREAD_MUTEX_INITIALIZER;
  
  /* FUNCTION DECLARATION */
  
  /*We define thread exit functions so that each pin 
  is lowered by the thread in which it is used avoiding
  race condition between the signal handler of the main thread
  and the other threads*/
  void exitingThreadTask1(void* arg);
  void exitingThreadTask2(void* arg);
  void exitingThreadTask3(void* arg);
  
  void* task1(void *arg); //thread function for the motion sensor
  void* task2(void *arg); //thread function for the temperature reading
  void* task3(void *arg); //thread function to post data on IOT platforms
  
  /*Signal handler to return from pause*/
  void sig_handler(int signo);
  
  int main()
  {
      int err;
      sigset_t omask, mask;
      pthread_t thread_motionSensor;
      pthread_t thread_tempReading;
      pthread_t thread_platformPost;
  
      printf("Created threads IDs\n");
  
      if (wiringPiSetup()&lt;0)
      {
          printf("WiringPi error\n");
          return -1;
      }
      printf("WiringPi is ok\n");
  
      if (signal(SIGQUIT, sig_handler)==SIG_ERR)
          printf("Error on recording SIGQUITHANDLER\n");
      if (signal(SIGINT, sig_handler)==SIG_ERR)
          printf("Error on recording SIGINTHANDLER\n");
      if (signal(SIGTERM, sig_handler)==SIG_ERR)
          printf("Error on recording SIGTERMHANDLER\n");
  
      /*Create a new mask to block all signals for the following thread*/
      sigfillset(&amp;mask);
      pthread_sigmask(SIG_SETMASK, &amp;mask, &amp;omask);
      printf("Trying to create threads\n");
      if ((err = pthread_create (&amp;thread_motionSensor, NULL, task1, NULL))!=0)
      {
      printf("Thread 1 not created: error %d\n", err);
          err_exit((const char)err, "pthread_create error");
      }
      printf("Thread 1 created. Trying to create Thread 2\n");
      if((err = pthread_create (&amp;thread_tempReading,   NULL, task2, NULL))!=0)
      {
      printf("Thread 2 not created: error %d\n", err);
          err_exit((const char)err, "pthread_create error");
      }
      printf("Thread 2 created. Trying to create Thread 3\n");
      if ((err = pthread_create (&amp;thread_platformPost, NULL, task3, NULL))!=0)
      {
       printf("Thread 3 not created: error %d %d\n", err);
           err_exit((const char)err, "pthread_create error");
      }
      printf("Thread 3 created\n");
      /*The main thread must block the SIGALRM but catch SIGINT
      SIGQUIT, SIGTERM, SIgkILL*/
      sigemptyset(&amp;omask);
      sigaddset(&amp;omask, SIGINT);
      sigaddset(&amp;omask, SIGQUIT);
      sigaddset(&amp;omask, SIGKILL);
      sigaddset(&amp;omask, SIGTERM);
  
      pthread_sigmask(SIG_UNBLOCK, &amp;omask, NULL);
      printf("Main thread waiting for signal\n");
      pause();
      printf("Exit signal received: cancelling threads\n");
  
      pthread_cancel(thread_motionSensor);
      pthread_cancel(thread_tempReading);
      pthread_cancel(thread_platformPost);
      pthread_join(thread_motionSensor, NULL);
      pthread_join(thread_tempReading,  NULL);
      pthread_join(thread_platformPost, NULL);
      printf("Exiting from main thread and process\n");
      exit(0);
  }
  
  void* task1(void *arg)
  {
      //INITIALIZING
      pthread_cleanup_push(exitingThreadTask1, NULL);
      while(1)
      {
          //do stuff1
      }
      pthread_cleanup_pop(0);
      pthread_exit(0);
  
  }
  
  void* task2(void *arg)
  {
      static const unsigned char schedule_time = 5;
      int signo, err;
      /*
      We set a local mask with SIGALARM for the function sigwait
      All signals have already been blocked
      */
      sigset_t alarm_mask;
      sigemptyset(&amp;alarm_mask);
      sigaddset(&amp;alarm_mask, SIGALRM);
      alarm(schedule_time);
      pthread_cleanup_push(exitingThreadTask2, NULL);
      while (1)
      {
          err = sigwait(&amp;alarm_mask, &amp;signo); //signo == SIGALRM check
          if (err!=0)
              err_exit(err, "sigwait failed\n");
          //do stuff
          alarm(schedule_time);
      }
      pthread_cleanup_pop(0);
      pthread_exit(0);
  }
  
  void* task3(void *arg)
  {
      pthread_cleanup_push(exitingThreadTask3, NULL);
      while(1)
      {
          pthread_mutex_lock(&amp;g_new_pic_m);
          while(g_new_pic_flag==FALSE)
          {
              pthread_cond_wait(&amp;g_new_pic_cond, &amp;g_new_pic_m);
          }
          pthread_mutex_unlock(&amp;g_new_pic_m);
          //do stuff
      }
      pthread_cleanup_pop(0);
      pthread_exit(0);
  
  }
  
  void exitingThreadTask1(void* arg)
  {
      printf("Thread of task 1 exiting\n");
      digitalWrite(OUTPIN, LOW);
      digitalWrite(INPIN, LOW);
      printf("Pins lowered\n");
      pthread_exit((void*)0);
  }
  
  void exitingThreadTask2(void* arg)
  {
      printf("Thread of task 2 exiting\n");
      digitalWrite(DHTPIN, LOW);
      printf("Pin lowered\n");
      pthread_exit((void*)0);
  }
  
  void exitingThreadTask3(void* arg)
  {
      printf("Thread of task 3 exiting\n");
      pthread_exit((void*)0);
  }
  
  void sig_handler(int signo)
  {
      printf("Running handler to return from pause\n");
      return;
  }
  </code></pre>