Return to the Lab #4 Page

#include <stdio.h>
#include <signal.h>
#include <siginfo.h>
#include <wait.h>
#include <ucontext.h>

/*
 * The previous example showed a signal handler.
 * This one shows a "signal action function"
 * The principle difference is that this method
 * allows us to more precisely determine what 
 * caused a signal, &c.
 *
 * Send the child various signals and observe operation.
 *
 * see man pages: sigaction, siginfo, wait
 * see /usr/sys/includewait.h 
 */

void ChildHandler (int sig, siginfo_t *sip, void *notused)
{
  int status;

    printf ("The process generating the signal is PID: %d\n", sip->si_pid);
    fflush (stdout);

    status = 0;
    /* The WNOHANG flag means that if there's no news, we don't wait */
    if (sip->si_pid == waitpid (sip->si_pid, &status, WNOHANG))
    {
        /* A SIGCHLD doesn't necessarily mean death -- a quick check */
        /* Not necessarily complete */
        if (WIFEXITED(status)) 
        {
          printf ("Voluntary exit.\n");
          goto done;
        }
          
        if (WIFSTOPPED(status)) 
        {
          printf ("Suspended.\n");
          goto done;
        }

        if ( (WTERMSIG(status) <= 12) || (WTERMSIG(status) == 15))
        {
          printf ("Croaked");
          goto done;
        }
 
        printf ("Nothing interesting\n");
done:;
    }
    else
    {
      /* If there's no news, we're probably not interested, either */
      printf ("Uninteresting\n");
    }
}

int main()
{

  struct sigaction action;

  action.sa_sigaction = ChildHandler; /* Note use of sigaction, not handler */
  sigfillset (&action.sa_mask);
  action.sa_flags = SA_SIGINFO; /* Note flag - otherwise NULL in function */
 
  sigaction (SIGCHLD, &action, NULL);

  fork();

  while (1)
  {
    printf ("PID: %d\n", getpid());
    sleep(1);
  }
}