哪个线程处理信号?

我有2个线程(thread1和thread2)。 我有SIGINT信号处理。 每当SIGINT发生时,线程2都应该处理信号。 为此我写下了程序

 void sig_hand(int no) //signal handler { printf("handler executing...\n"); getchar(); } void* thread1(void *arg1) //thread1 { while(1) { printf("thread1 active\n"); sleep(1); } } void * thread2(void * arg2) //thread2 { signal(2, sig_hand); while(1) { printf("thread2 active\n"); sleep(3); } } int main() { pthread_t t1; pthread_t t1; pthread_create(&t1, NULL, thread1, NULL); pthread_create(&t2, NULL, thread2, NULL); while(1); } 

我编译并运行程序。 每1秒打印一个“thread1 active”,每3秒打印一次“thread2 active”。

现在我生成了SIGINT 。 但是它的打印“thread1 active”和“thread2 active”消息就像上面那样。 我再次生成SIGINT ,现在每3秒钟只有“thread2 active”消息正在打印。 我又一次生成了SIGINT ,现在所有的线程都被阻塞了。

所以我明白了,第一次主线程执行信号处理程序。 第二次thread1执行处理程序,最后thread2执行信号处理程序。

我怎样才能编写的代码,每当信号发生,只有线程2必须执行我的信号处理程序?

Solutions Collecting From Web of "哪个线程处理信号?"

如果你发送一个信号给一个进程,那么进程中的哪个线程将处理这个信号是不确定的。

根据pthread(7)

POSIX.1还要求线程共享一系列其他属性(即,这些属性是进程范围而不是每个线程):

– 信号处置

POSIX.1区分了针对整个过程的信号和针对单个线程的信号的概念。 根据POSIX.1,流程控制信号(例如,使用kill(2)发送)应由流程内的单个任意选择的线程处理。


如果你想在你的进程中的专用线程来处理一些信号,这里是一个来自pthread_sigmask(3)的例子,告诉你如何做到这一点:

下面的程序会阻塞主线程中的一些信号,然后创建专用线程通过sigwait(3)获取这些信号。 以下shell会话演示了它的用法:

 $ ./a.out & [1] 5423 $ kill -QUIT %1 Signal handling thread got signal 3 $ kill -USR1 %1 Signal handling thread got signal 10 $ kill -TERM %1 [1]+ Terminated ./a.out 

节目源

 #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <errno.h> /* Simple error handling functions */ #define handle_error_en(en, msg) \ do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) static void * sig_thread(void *arg) { sigset_t *set = arg; int s, sig; for (;;) { s = sigwait(set, &sig); if (s != 0) handle_error_en(s, "sigwait"); printf("Signal handling thread got signal %d\n", sig); } } int main(int argc, char *argv[]) { pthread_t thread; sigset_t set; int s; /* Block SIGQUIT and SIGUSR1; other threads created by main() will inherit a copy of the signal mask. */ sigemptyset(&set); sigaddset(&set, SIGQUIT); sigaddset(&set, SIGUSR1); s = pthread_sigmask(SIG_BLOCK, &set, NULL); if (s != 0) handle_error_en(s, "pthread_sigmask"); s = pthread_create(&thread, NULL, &sig_thread, (void *) &set); if (s != 0) handle_error_en(s, "pthread_create"); /* Main thread carries on to create other threads and/or do other work */ pause(); /* Dummy pause so we can test program */ } 

请仔细阅读signal(7) & pthread(7) & pthread_kill(3) & sigprocmask(2) & pthread_sigmask(3) – 您可以使用它(在不需要的线程中阻止SIGINT )。 另请阅读一个pthread教程

避免使用信号在线程之间进行通信或同步。 考虑互斥锁( pthread_mutex_lock等)和条件变量( pthread_cond_wait等)。

如果其中一个线程运行事件循环 (例如,围绕轮询(2) …)考虑使用signalfd(2)