我已经用sigsetjmp和siglongjmp编写了一个分段错误处理程序。一旦它转到信号处理程序,我就调用siglongjmp,以便跳过错误的指令。
问题是,我再次想引起sigsegv并转到同一个处理程序,但现在sigsetjmp将返回1。
如何重置sigsetjmp?
这是我的代码:
#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
#include <setjmp.h>
sigjmp_buf env, env1;
void SIGSEGV_handler(int signal)
{
printf("Segmentation fault caught\n");
siglongjmp(env, 1);
}
int main()
{
void * allocation;
size_t size;
static int devZerofd = -1;
struct sigaction sa, sa1;
sa.sa_handler=(void*)SIGSEGV_handler;
sigaction(SIGSEGV, &sa, NULL);
if ( devZerofd == -1 ) {
devZerofd = open("/dev/zero", O_RDWR);
if ( devZerofd < 0 )
perror("open() on /dev/zero failed");
}
allocation = (caddr_t) mmap(0, 5000, PROT_READ|PROT_NONE, MAP_PRIVATE, devZerofd, 0);
if ( allocation == (caddr_t)-1 )
fprintf(stderr, "mmap() failed ");
if ( mprotect((caddr_t)allocation, 5000, PROT_NONE) < 0 )
fprintf(stderr, "mprotect failed");
else
printf("mprotect done: memory allocated at address %u\n",allocation);
if(sigsetjmp(env, 1)==0) {
printf("Causing SIGSEGV: 1\n");
strcpy(allocation,"Hello, how are you");
}
/****** This can't be done again as sigsetjmp won't return 0*****/
/*
if(sigsetjmp(env, 1)==0) {
printf("Causing SIGSEGV: 1\n");
strcpy(allocation,"Hello, how are you");
}
*/
}
最佳答案
您误解了[sig]setjmp
的工作原理。如果您取消注释您认为不起作用的代码,编译并运行它,您将看到它实际上起作用。
无法通过调用setjmp
使longjmp
返回零。如果您第二次调用setjmp
本身,即使使用相同的jmp_buf
(正如您在这里所做的那样),它也将第二次返回零。
顺便说一下,您有一个bug:您没有正确设置sigaction
参数结构。你应该这样做:
struct sigaction sa;
sa.sa_handler = SIGSEGV_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGSEGV, &sa, 0);
使用
mmap
有点不合适,但实际上不是很麻烦。在大多数当前平台上,您不需要/dev/zero
,只需使用MAP_ANON
(有些平台拼写它MAP_ANONYMOUS
)和-1 fd参数。你应该使用getpagesize
然后要求一整页。关于c - 我们是否可以将sigsetjmp重置为再次返回“0”(重置sigsetjmp)?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6985463/