我正在与线程一起使用,正在经历信号的反应。我知道printf
系列功能不是信号安全功能,但为简单起见,我使用它。据说
当信号传递到已建立信号处理程序的多线程进程时,内核会任意选择一个 将信号传递到的过程中的线程 该线程中的处理程序。 传统的信号语义。这对于没有意义 多次执行信号处理动作的过程 对单个信号的响应。
要体验粗体文本,我编写了以下基本代码,但是当我按Ctrl-C
时,得到的线程ID不同于创建的线程ID。这是谁?为什么我看不到其他线程可以捕获信号。
#include <pthread.h>
#include <stdio.h>
#include <signal.h>
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
int count = 0;
int globerr;
void *inc(void *arg) {
fprintf(stderr, "Thread id = %d\n", (int)pthread_self());
sleep(2);
int error;
for (int i = 0; i < 15; ++i) {
if (error = pthread_mutex_lock(&mtx)) {
globerr = error;
return 0;
}
count++;
printf("thread id = %d, count = %d\n", pthread_self(), count);
if (count == 20) {
printf("thread id = %d, SIGNAL count = %d\n", pthread_self(), count);
pthread_cond_signal(&cv);
}
if (error = pthread_mutex_unlock(&mtx)) {
globerr = error;
return 0;
}
}
}
void* watcher(void *arg) {
fprintf(stderr, "Thread id = %d\n", (int)pthread_self());
sleep(2);
int error;
if (error = pthread_mutex_lock(&mtx)) {
globerr = error;
return 0;
}
while (count < 20) {
printf("watcher thread id = %d, BLOCKING count = %d\n", pthread_self(), count);
pthread_cond_wait(&cv, &mtx);
printf("watcher thread id = %d, UNBLOCKING count = %d\n", pthread_self(), count);
}
printf("watcher thread id = %d, count = %d\n", pthread_self(), count);
if (error = pthread_mutex_unlock(&mtx)) {
globerr = error;
return 0;
}
}
static void signal_handler(int sig){
if (sig == SIGINT)
printf("Caught signal for Ctrl+C, Thread id = %d\n", (int)pthread_self());
pthread_cancel(pthread_self());
}
int main(void) {
struct sigaction sigact;
sigact.sa_handler = signal_handler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
sigaction(SIGINT, &sigact, (struct sigaction *)NULL);
pthread_t t[3];
for (int i = 0; i < 2; ++i) {
pthread_create(&t[i], 0, inc, 0);
}
pthread_create(&t[2], 0, watcher, 0);
sleep(3);
for (int i = 0; i < 3; ++i) {
pthread_join(t[i], 0);
}
}
示例输出
MacBook-Pro-2:cmake-build-debug soner$ ./client
Thread id = 171921408
Thread id = 172457984
Thread id = 172994560
^CCaught signal for Ctrl+C, Thread id = 360719808
^CCaught signal for Ctrl+C, Thread id = 171921408
^CCaught signal for Ctrl+C, Thread id = 172457984
^CCaught signal for Ctrl+C, Thread id = 172994560
360719808
是谁?
答案 0 :(得分:1)
如果您多次调用pthread_create
,则您的程序有四个线程:第四个是初始线程,该线程从程序开始就存在。您可以将其视为线程过程为main
的线程。
在这样的程序中,您应该专用一个线程来进行信号处理。您分四个步骤进行操作:
main
中,在创建任何线程之前,请使用pthread_sigmask
来阻止所有信号,但那些信号指示同步致命事件(SIGABRT,SIGBUS,SIGFPE,SIGILL,SIGSEGV ,SIGSYS和SIGTRAP)。不要安装任何信号处理程序。sigwaitinfo
以获取您关心的信号。这必须至少包括表示外部终止或挂起请求的信号:SIGINT,SIGHUP,SIGPWR,SIGQUIT,SIGTERM,SIGTSTP,SIGXCPU。如果使用子进程,则还必须包括SIGCHLD。select
上进行封锁。