- 论坛徽章:
- 0
|
我读sysvinit的代码,发现它关于SIGSEGV的处理很奇怪,在segv_handler中,它作了一些logging,然后fork一个子进程出来重新抛出,随后父进程等待它结束再继续运行。
我原来理解是这样做可以在产生dump后,让主程序尝试从错误点继续,如果直接在主程序里面重新产生SIGSEGV的话,将会直接退出,所以fork后再产生。但我在做了测试后,发现这样产生的core dump,里面的堆栈信息完全不对,根本不是主程序中产生错误的那个指令,而是子进程中的产生位置, 这样的话,这种做法在现实的程序中就完全没有实用性了?
不知道有哪位研究过这段代码,请教一下, 关键代码如下:
- void segv_handler(int sig, struct sigcontext ctx)
- {
- char *p = "";
- int saved_errno = errno;
- //日志
- if ((void *)ctx.eip >= (void *)do_sleep &&
- (void *)ctx.eip < (void *)main)
- p = " (code)";
- initlog(L_VB, "PANIC: segmentation violation at %p%s! "
- "sleeping for 30 seconds.", (void *)ctx.eip, p);
-
- // 在子进程中产生SIGSEGV以及core dump
- coredump();
-
- // 等待30秒, 再尝试恢复主程序执行
- do_sleep(30);
- errno = saved_errno;
- }
- void coredump(void)
- {
- static int dumped = 0;
- struct rlimit rlim;
- sigset_t mask;
- if (dumped) return;
- dumped = 1;
- if (fork() != 0) return;
- sigfillset(&mask);
- sigprocmask(SIG_SETMASK, &mask, NULL);
- rlim.rlim_cur = RLIM_INFINITY;
- rlim.rlim_max = RLIM_INFINITY;
- setrlimit(RLIMIT_CORE, &rlim);
- chdir("/");
- signal(SIGSEGV, SIG_DFL);
- raise(SIGSEGV);
- sigdelset(&mask, SIGSEGV);
- sigprocmask(SIG_SETMASK, &mask, NULL);
- do_sleep(5);
- exit(0);
- }
复制代码 |
|