1
votes

I wrote a program to intentionally let the child process to trigger SIGSEGV. However, I want the child process to terminate abnormally. Right now I use exit() in the signal handler. But exit() call will always generate a normal termination. Which function should I use to achieve that? Another question is how can I let the parent process know that the child process terminates because of 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");
    }
  }
1
There is the _exit() function, which doesn't call the atexit() functions, but only terminates (absormaly) immidiately. - wildplasser
I get a whole bundle of errors from running your code through cc sigsegv.c (after saving it to sigsegv.c), with gcc 4.7.2. Can you please fix the code so that it compiles? - user
abort() or kill() if you want SIGSEGV. - Stargateur
I suppose you could reset the signal handler and then trigger a segmentation violation yourself? (For example by dereferencing the null pointer.) That will trigger a SIGSEGV and end the process, but of course the error will occur at some location other than that where the original error occured. - user
How do you define abnormal termination? - n. 1.8e9-where's-my-share m.

1 Answers

2
votes
  1. To cause the child exit by a signal, unregister a handler, unblock the signal, and raise it.

    // 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);
    

    You need to unblock if you are in a handler for that signal, for example. It is recommended to use sigaction instead of plain C standard signal, this is however not shown here.

  2. To check in the parent process whether a child was terminated by a signal:

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