免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2592 | 回复: 0
打印 上一主题 下一主题

关于init代码中捕捉SIGSEGV的处理问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-11-06 11:17 |只看该作者 |倒序浏览
我读sysvinit的代码,发现它关于SIGSEGV的处理很奇怪,在segv_handler中,它作了一些logging,然后fork一个子进程出来重新抛出,随后父进程等待它结束再继续运行。

我原来理解是这样做可以在产生dump后,让主程序尝试从错误点继续,如果直接在主程序里面重新产生SIGSEGV的话,将会直接退出,所以fork后再产生。但我在做了测试后,发现这样产生的core dump,里面的堆栈信息完全不对,根本不是主程序中产生错误的那个指令,而是子进程中的产生位置, 这样的话,这种做法在现实的程序中就完全没有实用性了?

不知道有哪位研究过这段代码,请教一下, 关键代码如下:

  1. void segv_handler(int sig, struct sigcontext ctx)
  2. {
  3.     char    *p = "";
  4.     int saved_errno = errno;

  5.     //日志
  6.     if ((void *)ctx.eip >= (void *)do_sleep &&
  7.         (void *)ctx.eip < (void *)main)
  8.         p = " (code)";
  9.     initlog(L_VB, "PANIC: segmentation violation at %p%s! "
  10.           "sleeping for 30 seconds.", (void *)ctx.eip, p);
  11.    
  12.     // 在子进程中产生SIGSEGV以及core dump
  13.     coredump();
  14.    
  15.     // 等待30秒, 再尝试恢复主程序执行
  16.     do_sleep(30);
  17.     errno = saved_errno;
  18. }

  19. void coredump(void)
  20. {
  21.     static int      dumped = 0;
  22.     struct rlimit       rlim;
  23.     sigset_t        mask;

  24.     if (dumped) return;
  25.     dumped = 1;

  26.     if (fork() != 0) return;

  27.     sigfillset(&mask);
  28.     sigprocmask(SIG_SETMASK, &mask, NULL);

  29.     rlim.rlim_cur = RLIM_INFINITY;
  30.     rlim.rlim_max = RLIM_INFINITY;
  31.     setrlimit(RLIMIT_CORE, &rlim);
  32.     chdir("/");

  33.     signal(SIGSEGV, SIG_DFL);
  34.     raise(SIGSEGV);
  35.     sigdelset(&mask, SIGSEGV);
  36.     sigprocmask(SIG_SETMASK, &mask, NULL);

  37.     do_sleep(5);
  38.     exit(0);
  39. }


复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP