1

In my program, I expected thread A to periodically send SIGUSR1 to thread B. In thread B, it will block at sigwait. As for what to do when SIGUSR1 is received, I am not defining it yet. Below is my code. However, the program terminates at once, and the output is User defined signal 1.

void usr1_handler();

int main(int argc, char const *argv[])
{
   pthread_t tid;
   pthread_attr_t attr_obj;
   void *thread(void *);

   pthread_attr_init(&attr_obj);
   pthread_attr_setdetachstate(&attr_obj, PTHREAD_CREATE_DETACHED);
   pthread_create(&tid, &attr_obj, thread, (void *)NULL);

   while(1)
   {
    int ret = pthread_kill(tid, SIGUSR1);
    sleep(5);
   }
    return 0;
}

void *thread(void *dummy)
{
    int sig;
   sigset_t sigmask;                 
   struct sigaction action;

   /* set up signal mask to block all in main thread */
   sigfillset(&sigmask);
   pthread_sigmask(SIG_BLOCK, &sigmask, (sigset_t *)0);

   for (;;)
   {
    int err = sigwait(&sigmask, &sig);
      /* define what to do with sig here */
    printf("sig is %d\n", sig);
   }

   pthread_exit((void *)NULL);
}
HuangJie
  • 1,488
  • 1
  • 16
  • 33
  • 1
    The `SIGUSR` signal is likely delivered before the child thread has blocked all signals and reached `sigwait()`. – Andrew Henle Jul 06 '16 at 14:02
  • @AndrewHenle Thanks for your reply. But the main thread will send the signal in the while(1) loop forever, even if the first one signal is lost, the rest are still delivered, right? – HuangJie Jul 06 '16 at 14:10
  • @HuangJie If this is indeed what happened, your program has already crashed after the first signal was sent – Ishay Peled Jul 06 '16 at 14:14
  • @IshayPeled Thanks for your reply. Yes, I think so. I add some print in the while(1) loop. However, the program terminates after the main function executes pthread_kill for the first time. – HuangJie Jul 06 '16 at 14:16
  • That explains it, what happens is that you send the signal once, the other thread has not set block yet and that causes your application to crash – Ishay Peled Jul 06 '16 at 14:19
  • I personally avoid using signals for communication, there are much nicer mechanisms depending on what you want to do – Ishay Peled Jul 06 '16 at 14:20

2 Answers2

0

Currently nothing is preventing the main function from calling pthread_kill before the created thread sets up its signal handling. Make sure the calls to sigfillset, etc... complete before the main function calls: int err = sigwait(&sigmask, &sig);.

Since you're already using pthreads, use a mutex and a shared flag variable:

The easiest solution is to move the signal handling, from the function thread into main, before the call to pthread_create.

2501
  • 25,460
  • 4
  • 47
  • 87
0

You're doing it wrong. You explicitly arrange for SIGUSR1 to be unblocked in the thread, but that is precisely the wrong thing to do. Some documentation does not make it clear (e.g. the Linux manpage for sigwait()), but POSIX says:

The signals defined by set shall have been blocked at the time of the call to sigwait(); otherwise, the behavior is undefined.

(Emphasis added.)

Do not overlook @AndrewHenle's and @2501's comments about a race condition, however. You have that too. I agree with @2501 that the easiest way to solve that is to set up the signal mask in the main thread, so that the other inherits it. Do not fail to restore the main thread's signal mask after launching the other thread, however, else you may find your program hard to kill.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157