2009-05-27 128 views
6

我正在编写一个程序,带有主线程和一些工作线程,并且我希望获得信号处理权限。我的问题是这样的:主/从线程和信号处理

主线程启动并完成所有分配

主线程设置一个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方法是我正在寻找。我要的是:

  • 找到一种方法,所有的线程是 阻塞阻塞调用返回从这些调用 。
  • 或者杀死除主要的所有线程外的所有线程。

回答

4

这是我通常在主应用程序线程做:


/* 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条件变量,这样就可以通过从主线程中创建一个“事件”来唤醒任意多个线程。

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

+0

是的。大多数人使用pthread或Win32/MFC实现线程 – Kieveli 2009-05-27 16:47:02

+0

不,我不认为这是好的,因为它不会将我从阻塞选择呼叫或sem_wait呼叫唤醒。 也许我可以用pthread_condition替换我的信号量,但信号量抽象真的适合我的同步模型。 – shodanex 2009-05-28 08:12:09

1

你的计划看起来不错。你迫使一个线程处理系统信号。你需要使用pthread-sigmask()来屏蔽你工作线程中的某些信号。

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