我们可以重新此时sigsetjmp返回" 0 QUOT;再次(复位此时sigsetjmp)? [英] Can we reset sigsetjmp to return "0" again (Reset sigsetjmp)?

查看:138
本文介绍了我们可以重新此时sigsetjmp返回" 0 QUOT;再次(复位此时sigsetjmp)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经写了段故障处理程序,利用此时sigsetjmp和siglongjmp。一旦它进入信号处理程序,使出现故障的指令被跳过我调用siglongjmp。

问题是,我再次希望引起SIGSEGV并转到相同的处理,但现在此时sigsetjmp将返回1。

如何重置此时sigsetjmp?

下面是我的code:

 的#include<&stdio.h中GT;
#包括LT&;&memory.h GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&unistd.h中GT;
#包括LT&; SYS / mman.h>
#包括LT&; SYS / types.h中>
#包括LT&;&fcntl.h GT;
#包括LT&;&signal.h中GT;
#包括LT&;&SETJMP.H GT;sigjmp_buf ENV,ENV1;无效SIGSEGV_handler(INT信号)
{
  的printf(分段错抓\\ n);
  siglongjmp(ENV,1);
}诠释的main()
{
 void *的分配;
 为size_t的大小;
 静态INT devZerofd = -1;
 结构sigaction的SA,SA1; sa.sa_handler =(无效*)SIGSEGV_handler;
 的sigaction(SIGSEGV,&安培; SA,NULL); 如果(devZerofd == -1){
     devZerofd =打开(/开发/零,O_RDWR);
     如果(devZerofd℃,)
         PERROR(在/ dev的open()/零失败);
  } 分配=(采用caddr_t)MMAP(0,5000,PROT_READ | PROT_NONE,MAP_PRIVATE,devZerofd,0); 如果(分配==(采用caddr_t)-1)
    fprintf中(标准错误,mmap()的失败); 如果(则mprotect((采用caddr_t)分配,5000,PROT_NONE)℃的)
     fprintf中(标准错误,mprotect的失败);
 其他
     的printf(则mprotect完成:内存地址分配%U \\ N,分配); 如果(此时sigsetjmp(ENV,1)== 0){
      的printf(造成SIGSEGV:1 \\ n);
      的strcpy(分配,你好,你好);
  }  / ******这不能作为再次做此时sigsetjmp不会返回0 ***** /
  / *  如果(此时sigsetjmp(ENV,1)== 0){
      的printf(造成SIGSEGV:1 \\ n);
      的strcpy(分配,你好,你好);
  }
   * /
 }


解决方案

您误解了如何 [SIG]的setjmp 的作品。如果您取消注释code,你认为行不通,编译并运行它,你会发现它实际上工作。

的setjmp 无法进行调用的longjmp 返回零。如果你调用的setjmp 自身,第二个时间,即使采用相同的 jmp_buf (如你在这里做的),它会返回零的第二次。

您有一个错误,顺便说一句:你没有设置你的的sigaction 参数结构正常。你应该这样做:

 结构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 ,然后请求页面的整数。

I have written a segmentation fault handler, using sigsetjmp and siglongjmp. Once it goes to the signal handler, i invoke siglongjmp so that the faulty instruction is skipped.

Problem is, i again want to cause SIGSEGV and go to the same handler, but now sigsetjmp will return 1.

How to reset sigsetjmp?

Here is my code:

#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");
  }
   */
 }

解决方案

You have misunderstood how [sig]setjmp works. If you uncomment the code that you think won't work, compile it, and run it, you will see that it does in fact work.

setjmp cannot be made to return zero by calling longjmp. If you call setjmp itself a second time, even with the same jmp_buf (as you do here), it will return zero a second time.

You have a bug, by the way: you didn't set up your sigaction parameter structure correctly. You should have done this:

struct sigaction sa;

sa.sa_handler = SIGSEGV_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGSEGV, &sa, 0);

The use of mmap is a little infelicitous, but not actually buggy. You don't need /dev/zero on most current platforms, you can just use MAP_ANON (some platforms spell it MAP_ANONYMOUS) and a -1 fd argument. And you should be using getpagesize and then asking for a whole number of pages.

这篇关于我们可以重新此时sigsetjmp返回&QUOT; 0 QUOT;再次(复位此时sigsetjmp)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆