我们可以重置sigsetjmp再次返回“0”(Reset sigsetjmp)吗?

我写了一个分段error handling程序,使用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"); } */ } 

Solutions Collecting From Web of "我们可以重置sigsetjmp再次返回“0”(Reset sigsetjmp)吗?"

你误解了[sig]setjmp工作方式。 如果您取消注释了您认为无效的代码,将其编译并运行,您将发现它确实可行。

通过调用longjmp不能使setjmp返回零。 如果您再次调用setjmp本身,即使使用相同的jmp_buf (与您在此处执行的操作相同),也会再次返回零。

顺便说一句,您有一个错误:您没有正确设置您的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 ,然后要求一整页的页面。