无法第二次重新分配信号处理程序
Unable to reassign signal handler second time
我有一个简单的代码,它使用两个信号处理程序来处理 "Segmentation fault" 信号。第一个在信号发生时起作用,在 longjmp
之后,我为该信号重新分配处理程序和第二个。不幸的是,代码流没有到达必要的处理程序,我仍然得到 "Segmentation fault"。
#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;
}
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. It has a good chapter on signal handling 是一个很好的资源。
我有一个简单的代码,它使用两个信号处理程序来处理 "Segmentation fault" 信号。第一个在信号发生时起作用,在 longjmp
之后,我为该信号重新分配处理程序和第二个。不幸的是,代码流没有到达必要的处理程序,我仍然得到 "Segmentation fault"。
#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;
}
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. It has a good chapter on signal handling 是一个很好的资源。