【问题标题】:How to make a child process exit abnormally after receiving SIGSEGV?如何让子进程收到SIGSEGV后异常退出?
【发布时间】:2017-06-03 19:58:40
【问题描述】:

我写了一个程序,故意让子进程触发SIGSEGV。但是,我希望子进程异常终止。现在我在信号处理程序中使用 exit() 。但是 exit() 调用总是会产生一个正常的终止。我应该使用哪个功能来实现这一点?另一个问题是如何让父进程知道子进程因为 SIGSEGV 而终止?

extern char  etext, edata, end;
void handler() {
  pid_t pid;
  pid = getpid();

  char buf[100];
  snprintf(buf, 100, "child %d terminated by signal 11", (int)pid);
  psignal(SIGSEGV, buf);
  exit(-1);
}

int main(int argc, char **argv) {
  if (signal(SIGSEGV, handler) == SIG_ERR) {
    perror("signal error");
  }

  printf("First address beyond:\n");
  printf("    program text segment(etext)      %10p\n", &etext);
  printf("    initialized data segment(edata)  %10p\n", &edata);
  printf("    uninitialized data segment (end) %10p\n", &end);

  if (fork() == 0) {
    printf("from Child before\n");
    etext = 'a';
    printf("from Child after\n");
  } else {
    pid_t pid;
    int status;
    if ((pid == waitpid(-1, &status, 0)) >= 0) {
      printf("Handler reaped child %d\n", (int)pid);
    }
    printf("child WIFEXITED = %d, WEXITSTATUS = %d\n", WIFEXITED(status), WEXITSTATUS(status));
    if (WEXITSTATUS(status) == -3) {
      printf("Capture the exit code\n");
    }
  }

【问题讨论】:

  • 有 _exit() 函数,它不调用 atexit() 函数,而只是(非常)立即终止。
  • 使用 gcc 4.7.2 通过cc sigsegv.c(将其保存到sigsegv.c 之后)运行您的代码时,我遇到了一大堆错误。你能修复代码以便编译吗?
  • abort()kill() 如果你想要 SIGSEGV
  • 我想您可以重置信号处理程序,然后自己触发分段违规? (例如通过取消引用空指针。)这将触发 SIGSEGV 并结束进程,但当然错误将发生在某个位置而不是发生原始错误的位置。
  • 异常终止怎么定义?

标签: c linux process


【解决方案1】:
  1. 要通过信号使子进程退出,请取消注册处理程序,解除对信号的阻塞,然后raise 它。

    // unregister SIGSEGV handler
    signal(SIGSEGV, SIG_DFL);
    
    // unblock SIGSEGV
    sigset_t mask;
    sigemptyset (&mask);
    sigaddset (&mask, SIGSEGV);
    if (sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
        perror ("Could not unblock");
    
    // raise SIGSEGV
    raise (SIGSEGV);
    

    例如,如果您处于该信号的处理程序中,则需要解除阻塞。建议使用sigaction 而不是普通的C 标准signal,但是这里没有显示。

  2. 在父进程中检查子进程是否被信号终止:

    if (WIFSIGNALED(status)) {
        printf("child killed by signal %d\n", WTERMSIG(status));
    

【讨论】:

  • 感谢您的回答。有用。但是,在第 1 步中,我只需要 signal(SIGSEGV, SIG_DFL);为了达到目的,我在代码中进行了测试。为什么我需要解锁 SIGSEGV?
  • SIG_DFL 处理程序是做什么的?我可以修改自己的处理程序来做类似的事情吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-11
  • 1970-01-01
  • 2010-09-21
  • 2015-12-12
相关资源
最近更新 更多