user3015353
user3015353

Reputation: 29

How do I make child print the signal that killed it?

I have the following code where parent is creating multiple child processes and killing them afterwards. Once killed, I want to print what killed the child (signal in this case). However, the code isnt printing that. what seems to be the problem?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

int i;

static void signal_handler(int signo)
{
  if (signo == SIGUSR1)
  {
    printf("child %d received sigusr1\n", i + 1);
  }
}

int main(void)
{
  char buff[50];
  int status;

  if (signal(SIGUSR1, signal_handler) == SIGUSR1)
  {
    perror("Signal handling error");
  }

  pid_t cpid, count;

  for (i = 0; i < 5; i++)
  {
    cpid = fork();

    if (cpid == 0)
    {
      sleep(10);

      //exit(0);
    }
    else if (cpid > 0)
    {
      kill(cpid, SIGUSR1);
      int status;
      int n = waitpid(cpid, &status, 0);

      if (n != cpid)
      {
        perror("error");
      }

      if (WIFSIGNALED(status))
      { /* get WTERMSIG(status)    */
        printf("killed by signal=%d\n", WTERMSIG(status));
      }
    }
    else
    {
      perror("Fork error: ");
      exit(1);
    }
  }
}

Upvotes: 0

Views: 1027

Answers (3)

Kerrek SB
Kerrek SB

Reputation: 477110

Use waitpid instead, and be sure to handle both normal exit and killed-by-signal:

pid_t pid = fork();

if (pid == 0)
{
    exit(0);
}
else if (pid > 0)
{
    int status;
    int n = waitpid(pid, &status, 0);

    if (n != pid)                 { /* error */ }
    else if (WIFSIGNALED(status)) { /* get WTERMSIG(status)    */ }
    else if (WIFEXITED(status))   { /* get WEXITSTATUS(status) */ }
}
else if (pid < 0)
{
    /* error */
}

As you can see from the documentation, wait will wait for any child, not just the current one. And of course its entirely possible that the child exits normally before receiving the signal.

You can stop the child from exiting normally by calling pause, but the signal will only kill the child if it doesn't get handled. If the signal handler returns, pause returns, too.

Upvotes: 0

Duck
Duck

Reputation: 27552

WIFSIGNALED(stat_val) - Evaluates to a non-zero value if status was returned for a child process that terminated due to the receipt of a signal that was not caught

Your signals are being caught (when they are received before they exit).

You have other problems that others have mentioned.

Upvotes: 1

ichramm
ichramm

Reputation: 6642

Is this the actual code of your app?

printf("killed by signal=%d\n");
WTERMSIG(status);

If so, the second line has no effect, try changing it to:

printf("killed by signal=%d\n", WTERMSIG(status));

Upvotes: 0

Related Questions