【发布时间】:2011-09-09 22:29:18
【问题描述】:
我正在使用以下示例(基于 linux 中 pthread_sigmask 手册页中的示例):
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
/* Simple error handling functions */
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
static void * silly_worker(void *arg)
{
for(int index=0,max=5; index<max; ++index) {
printf("waiting %d of %d\n",index,max);
sleep(1);
}
puts("Finished waiting. Here comes the SIGSEGV");
strcpy(NULL,"this will crash");
}
static void *
sig_thread(void *arg)
{
sigset_t *set = (sigset_t *) 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;
pthread_t thread2;
sigset_t set;
int s;
/* Block SIGINT; other threads created by main() will inherit
a copy of the signal mask. */
sigemptyset(&set);
sigaddset(&set, SIGQUIT);
sigaddset(&set, SIGUSR1);
sigaddset(&set, SIGSEGV);
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 */
s = pthread_create(&thread2, NULL, &silly_worker, (void *) &set);
if (s != 0)
handle_error_en(s, "pthread_create");
pause(); /* Dummy pause so we can test program */
}
根据手册页,这应该捕获 silly_worker 线程生成的 SIGSEGV。但事实并非如此。事实上,我完全不确定哪个机构收到了信号。当程序运行时,我得到以下输出:
waiting 0 of 5
waiting 1 of 5
waiting 2 of 5
waiting 3 of 5
waiting 4 of 5
Finished waiting. Here comes the SIGSEGV
Segmentation fault
您可以看到信号处理程序没有输出“分段错误”字符串,因此它必须来自默认处理程序。如果是默认设置,那么它会破坏示例的目的 - 设置信号处理程序并捕获信号并对其进行处理。
我可以找到很多处理程序的示例,但它们都不适用于这种情况:它们都没有演示导致非常明显的 SIGSEGV 的线程,并在其自定义处理程序中捕获并报告错误。
问题仍然存在:如何获得自定义信号处理程序以从该 SIGSEGV 线程获取信号?
【问题讨论】:
-
这对 SIGINT 等其他信号有效吗?像 SIGSEGV 和 SIGILL 这样的一些信号是同步的,并且总是被传递给导致它们的线程。我不确定 sigwait 是否可以处理这些。
-
请注意,当 shell 看到您的进程被 SIGSEGV 信号杀死时,通常会打印“分段错误”。
-
它适用于其他信号,但这无济于事:我正在尝试专门捕获 SIGSEGV。在一个简短得多的示例中,在 main() 中只有一个循环并且没有线程,我可以捕获 SIGSEGV,完全没有问题。当线程开始发挥作用时,它似乎无法正常工作。
-
请注意,如果您使用
pthread_kill或raise将它们发送到特定线程,它也不适用于其他信号...
标签: c linux multithreading