【问题标题】:master / worker threads and signal handling主/工作线程和信号处理
【发布时间】:2010-10-29 07:11:33
【问题描述】:

我正在编写一个程序,有一个主线程和一些工作线程,我想正确处理信号。我的问题如下:

主线程启动并进行所有分配

主线程设置一个 SIGINT 信号处理程序

主线程启动工作线程。工作线程不需要特殊清理,但是它们可以在系统调用或信号量上休眠。

收到SIGINT时,我的理解是只有一个线程接收。因此,如果线程在系统调用或信号量上处于休眠状态,它们将不会被唤醒,我将无法 pthread_join 我的工作线程并在我的主线程中进行所有必要的清理。

以下信号处理程序可以解决我的问题吗?

void term(int sig)
{
    g_do_cleanup = 1;
    pthread_kill(worker_1_id, some_other_signal);
    ...
    pthread_kill(worker_2_id, some_other_signal);
}

我期望的是,在收到 SIGINT 后,所有线程都会收到另一个信号,退出阻塞调用,查看g_do_cleanup 标志并优雅退出。

欢迎任何关于如何正确执行此操作的评论或链接。

编辑: 我不是在寻找一种方法来唤醒在特定条件下等待的多个线程,所以我不认为 pthread_cond_signal 方法是我正在寻找的。我想要的是:

  • 找到一种方法,使所有线程 在阻塞调用返回时阻塞 来自这些调用。
  • 或者杀死除主线程之外的所有线程。

【问题讨论】:

    标签: c linux multithreading pthreads posix


    【解决方案1】:

    这是我通常在主应用线程中做的事情:

    
    /* before starting other threads */
    sigset_t sigs;
    sigemptyset( &sigs );
    sigaddset( &sigs, SIGTERM );
    sigaddset( &sigs, SIGINT );
    /* add other signals to handle */
    if ( pthread_sigmask( SIG_BLOCK, &sigs, 0 )) { /* handle error */ }
    /* can start threads now */
    ...
    /* in the main event loop */
    siginfo_t info;
    if ( sigwaitinfo( &sigs, &info ) == -1 ) { /* handle error */ }
    switch( info.si_signo )
    {
      case SIGTERM:
      case SIGINT: /* raise shutdown event */ break;
      default: /* other actions - log rotation, etc. */
    }
    ...
    

    这种方式信号成为常规应用程序事件 - 没有特殊的信号上下文限制等。 等待也可以通过sigtimedwait 超时完成,尽管 BSD 衍生产品不支持它。

    【讨论】:

      【解决方案2】:

      你的计划看起来不错。您正在强制一个线程处理系统信号。您需要使用 pthread-sigmask() 屏蔽工作线程中除其他信号之外的信号。

      我想我会用一个单独的线程来处理进程信号而不是主线程。在等待运行信号处理程序时,让它永远等待信号量或 sigwait() 或其他任何东西。将 pthread-kill 代码移出信号处理程序。只需设置开关,让信号等待线程将 other_signal 发送到工作线程并自行退出。

      【讨论】:

      • 使用信号在线程之间进行通信是错误的做法。许多线程库甚至不使用信号。最好使用线程库提供的线程同步机制,比如上面提到的条件变量。
      • 信号很原始,远非理想,但他的库显然支持它们,否则他不会问。他没有做很多次都没有成功的事情。
      • 这不是关于线程通信,而是关于线程终止。 pthread_cancel + 信号处理线程可能工作
      【解决方案3】:

      在我看来,您想要的是一个 pthread 条件变量,这样您就可以通过从主线程中选择一个“事件”来唤醒任意数量的多个线程。

      有关更多信息,请参阅 PTHREAD_COND_DESTROYPTHREAD_COND_BROADCAST 的手册页。

      【讨论】:

      • 是的。大多数人使用 pthread 或 Win32 / MFC 实现来处理线程
      • 不,我不认为这没问题,因为它不会将我从阻塞选择调用或 sem_wait 调用中唤醒。也许我可以用 pthread_condition 替换我的信号量,但信号量抽象确实适合我的同步模型。
      猜你喜欢
      • 1970-01-01
      • 2012-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-07
      • 2011-11-18
      • 2014-08-29
      • 1970-01-01
      相关资源
      最近更新 更多