我有一个简单的代码,该代码使用两个信号处理程序来处理“分段故障”信号。第一个在信号发生时起作用,在longjmp
之后,我为该信号重新分配了处理程序,第二个则进行了处理。不幸的是,代码流没有到达必要的处理程序,我仍然遇到“分段错误”。
#include <unistd.h>
#include <sys/syscall.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>
int i;
int ci;
jmp_buf m_env_buffer;
jmp_buf max_env_buffer;
void handler(int signum){
printf("sigsegv on i:[%d]", i);
ci = (++i);
longjmp(m_env_buffer,1);
}
void top_handler(int signum){
printf("sigsegv on max i:[%d]", i);
longjmp(max_env_buffer,10);
}
int main(void) {
signal(SIGSEGV, handler);
char * pstart = "loremipsum";
int m_cell = 0;
char m_cell_v;
int point;
point = setjmp(m_env_buffer);
if(point == 0){
for(i=0; ;i--){
m_cell_v = pstart[i];
}
}
//this wasn't invoked
signal(SIGSEGV, top_handler);
point = setjmp(max_env_buffer);
if(point == 0){
for(i=ci; ;i++){
char cur = pstart[i];
if(cur==10)
printf("\n");
printf("%c",cur);
}
}
puts("finish");
return 0;
}
答案 0 :(得分:0)
signal()
不应使用。它具有不可靠的语义。在系统上,当收到第二个SIGSEGV时,将执行默认操作(终止)。对signal()
的第二次调用实际上无效。
您应该改用sigaction()
。您可以使用以下函数代替signal()
:
void set_signal (int signum, void (*handler)(int))
{
struct sigaction act;
act.sa_handler = handler;
sigemptyset (&act.sa_mask);
act.sa_flags = SA_NODEFER;
act.sa_restorer = NULL;
sigaction (signum, &act, NULL);
}
将来,请阅读文档。 glibc manual是一个很好的资源。它在signal handling上有一章很好。