【问题标题】:pthread signal does not workpthread 信号不起作用
【发布时间】:2016-07-06 13:59:10
【问题描述】:

在我的程序中,我希望线程 A 定期向线程 B 发送 SIGUSR1。在线程 B 中,它将阻塞在 sigwait。至于收到SIGUSR1 时该怎么做,我还没有定义。下面是我的代码。但是,程序立即终止,输出为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);
}

【问题讨论】:

  • SIGUSR 信号很可能在子线程阻塞所有信号并到达sigwait() 之前传递。
  • @AndrewHenle 感谢您的回复。但是主线程会永远在while(1)循环中发送信号,即使第一个信号丢失了,其余的还是会传递的,对吧?
  • @HuangJie 如果确实是这样的话,你的程序在第一个信号发出后就已经崩溃了
  • @IshayPeled 感谢您的回复。是的,我想是这样。我在 while(1) 循环中添加了一些打印。但是,在main函数第一次执行pthread_kill后,程序就终止了。
  • 这就解释了,发生的情况是你发送了一次信号,另一个线程还没有设置阻塞,导致你的应用程序崩溃

标签: c multithreading signals


【解决方案1】:

你做错了。您明确安排SIGUSR1 在线程中被解除阻塞,但这恰恰是错误的做法。有些文档没有说清楚(例如sigwait() 的 Linux 联机帮助页),但 POSIX says

set 定义的信号在调用sigwait() 时应已被阻止;否则,行为未定义。

(已添加重点。)

但是,不要忽视 @AndrewHenle 和 @2501 的 cmets 关于比赛条件的问题。你也有。我同意@2501,解决这个问题的最简单方法是在主线程中设置信号掩码,以便其他人继承它。启动其他线程后,请务必恢复主线程的信号掩码,否则您可能会发现您的程序很难被杀死。

【讨论】:

【解决方案2】:

目前没有什么可以阻止主函数在创建的线程设置其信号处理之前调用pthread_kill。确保在主函数调用之前完成对sigfillset 等的调用:int err = sigwait(&sigmask, &sig);

由于您已经在使用 pthread,请使用互斥锁和共享标志变量:

最简单的解决方案是在调用 pthread_create 之前将信号处理从函数 thread 移动到 main

【讨论】:

    猜你喜欢
    • 2021-04-21
    • 2015-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-03
    • 1970-01-01
    相关资源
    最近更新 更多