我正在编写一个带有主线程和一些工作线程的程序,我希望正确处理信号。我的问题如下:
主线程启动并执行所有分配
主线程设置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方法是我正在寻找的。我想要的是:
答案 0 :(得分:4)
这是我通常在主app线程中做的事情:
/* 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衍生产品不支持它。
答案 1 :(得分:2)
听起来像你想要的是一个pthread条件变量,这样你就可以通过从主线程中选择一个“事件”来唤醒任意数量的多个线程。
有关详细信息,请参阅PTHREAD_COND_DESTROY和PTHREAD_COND_BROADCAST的手册页。
答案 2 :(得分:1)
你的计划似乎很好。您正在强制一个线程处理系统信号。您需要使用pthread-sigmask()屏蔽工作线程中除某些其他信号之外的信号。
我想我会使用一个单独的线程来处理过程信号而不是主控。让它在等待运行信号处理程序时等待信号量或sigwait()等等。将pthread-kill代码移出信号处理程序。只需设置开关并让信号等待线程将other_signal发送到工作线程并退出。