关于在醒目多线程环境中SIGSEGV [英] About catching the SIGSEGV in multithreaded environment
问题描述
我想知道是否有可能/推荐的办法赶上在多线程环境中的SIGSEGV信号。我在处理由类似提出的SIGSEGV特别感兴趣*((INT *)0)= 0。
I'd like to know if it is possible/the recommended way to catch the SIGSEGV signal in multithreaded environment. I am particularly interested in handling the SIGSEGV raised by something like '*((int *)0) = 0'.
有关此主题的一些阅读使我signal()和sigaction的(),它安装一个信号处理程序。虽然没有似乎多线程环境看好。然后,我尝试了sigwaitinfo(),接收信号在一个线程中使用事先pthread_sigmask()调用,阻止对其他信号。它致力于在其信号SIGSEGV引发的程度,用养(),线程内部或当它是由像发送到进程杀-SIGSEGV';然而,*(为(int *)0)= 0'还是终止进程。我的测试程序如下:
Some reading on this topic led me to signal() and sigaction(), which install a signal handler. While neither seem promising in multithreaded environment. I then tried the sigwaitinfo(), receiving the signals in one thread with a prior pthread_sigmask() call that blocks the signal on the others. It worked to the extent upon which the signal SIGSEGV was raised, using raise(), inside a thread or when it was sent to the process by something like 'kill -SIGSEGV'; however, *((int*)0) = 0' still kills the process. My test program is as follows
void block_signal()
{
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGSEGV);
sigprocmask(SIG_BLOCK, &set, NULL);
if (pthread_sigmask(SIG_BLOCK, &set, NULL)) {
fprintf(stderr, "pthread_sigmask failed\n");
exit(EXIT_FAILURE);
}
}
void *buggy_thread(void *param)
{
char *ptr = NULL;
block_signal();
printf("Thread %lu created\n", pthread_self());
// Sleep for some random time
{ ... }
printf("About to raise from %lu\n", pthread_self());
// Raise a SIGSEGV
*ptr = 0;
pthread_exit(NULL);
}
void *dispatcher(void *param)
{
sigset_t set;
siginfo_t info;
int sig;
sigemptyset(&set);
sigaddset(&set, SIGSEGV);
for (;;) {
sig = sigwaitinfo(&set, &info);
if (sig == -1)
fprintf(stderr, "sigwaitinfo failed\n");
else
printf("Received signal SIGSEGV from %u\n", info.si_pid);
}
}
int main()
{
int i;
pthread_t tid;
pthread_t disp_tid;
block_signal();
if (pthread_create(&disp_tid, NULL, dispatcher, NULL)) {
fprintf(stderr, "Cannot create dispatcher\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < 10; ++i) {
if (pthread_create(&tid, NULL, buggy_thread, NULL) {
fprintf(stderr, "Cannot create thread\n");
exit(EXIT_FAILURE);
}
}
pause();
}
没想到,程序段故障去世打印募集的线程ID代替。
Unexpectedly, the program dies with a segmentation fault instead of printing the raiser's thread id.
推荐答案
您code不调用的的sigaction(2),我相信它应该调用它。阅读也信号(7)。和信号作用(直通 sa_sigaction
字段应该做的东西(机专用)的 siginfo_t
来跳过问题的机器指令,或 MMAP
违规地址,或从信号处理程序返回你会得到的时候调用 siglongjmp
,否则 SIGSEGV
再次因为违规的机器指令重新启动。
Your code does not call sigaction(2), and I believe it should call it. Read also signal(7). And the signal action (thru sa_sigaction
field should do something (machine specific) with its siginfo_t
to skip the offending machine instruction, or to mmap
the offending address, or call siglongjmp
, otherwise when returning from the signal handler you'll get the SIGSEGV
again since the offending machine instruction is restarted.
您不能在另一个线程处理 SIGSEGV
,由于异步信号是线程特定的(见的这个答案),所以你尝试用来实现sigwaitinfo
不能工作。特别 SIGSEGV
被定向到违例线程
You cannot handle the SIGSEGV
in another thread, since asynchronous signals are thread specific (see this answer), so what you try to achieve with sigwaitinfo
cannot work. In particular SIGSEGV
is directed to the offending thread.
阅读也所有关于Linux信号的。
这篇关于关于在醒目多线程环境中SIGSEGV的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!