Signal Processing Notes

This contains links to information used in the lectures. Note that the code segments have less than and greater than replaced by < and > so that they display correctly.

Overview of Signal Handling

There are differences in signal handling between Berkeley (SunOS 4.2.1) like systems and System V (HP-UX) like systems

Resetting Signals

Restarting Signals

Signals - HP-UX

      Name        Number   Notes     Meaning
      ______________________________________________________________________
      SIGHUP        01     A         hangup
      SIGINT        02     A         interrupt
      SIGQUIT       03     A,B       quit
      SIGILL        04     A,B,C     illegal instruction
      SIGTRAP       05     A,B,C     trace trap
      SIGABRT       06     A,B       software generated abort; see abort(3C)
      SIGIOT        06     A,B       software generated signal
      SIGEMT        07     A,B       software generated signal
      SIGFPE        08     A,B       floating point exception
      SIGKILL       09     A,D,E,F   kill
      SIGBUS        10     A,B       bus error
      SIGSEGV       11     A,B       segmentation violation
      SIGSYS        12     A,B       bad argument to system call
      SIGPIPE       13     A         write on a pipe with no one to read it
      SIGALRM       14     A         alarm clock; see alarm(2)
      SIGTERM       15     A         software termination signal
      SIGUSR1       16     A         user defined signal 1
      SIGUSR2       17     A         user defined signal 2
      SIGCHLD       l8     G         death of a child (see WARNINGS below)
      SIGCLD        l8     G         death of a child (see WARNINGS below)
      SIGPWR        19     C,G       power fail (see WARNINGS below)
      SIGVTALRM     20     A         virtual timer alarm; see getitimer(2)
      SIGPROF       21     A         profiling timer alarm; see getitimer(2)
      SIGIO         22     G         asynchronous I/O signal; see select(2)
      SIGWINCH      23     G         window size change; see termio(7)
      SIGSTOP       24     D,E,H     stop
      SIGTSTP       25     H         stop signal generated from keyboard
      SIGCONT       26     F,G       continue after stop
      SIGTTIN       27     H         background read attempted from control
                                     terminal
      SIGTTOU       28     H         background write attempted to control
                                     terminal
      SIGURG        29     G         urgent data arrived on an I/O channel
      SIGLOST       30     A         file lock lost (NFS file locking)

      The letters in the Notes column in the table above indicate the action
      taken when the signal is received, and any special conditions on its
	use:
           A       The default action is to terminate the process.
           B       The default action of terminating the process also
                   generates a core image file if possible.
           C       The action is not reset to SIG_DFL before calling the
                   signal-catching function.
           D       The signal cannot be ignored.
           E       The signal cannot be caught.
           F       The signal will not be held off from a stopped process.
           G       The default action is to ignore the signal.
           H       The default action is to stop the process.
Note that SIGKILL and SIGSTOP cannot be caught or ignored.

Sending Signals in C programs

Sending Signals from Shells and from the keyboard

Catching and Ignoring Signals

Ignoring Signals

Catching Signals

POSIX Signal Handling

  • Example : POSIX signal handling posix.c
    #include <stdio.h>
    #include <signal.h>
    #include <errno.h>
    #include <unistd.h>
    
    /*                                         */
    /*                                         */
    /*SYNOPSIS                                 */
    /*      #include <signal.h>                */
    /*                                         */
    /*      int sigaction (                    */
    /*           int sig,                       signal to watch */
    /*           const struct sigaction *act,   action to take */
    /*           struct sigaction *oact         old action */
    /*      );                                 */
    /*      struct {                           */
    /*          void       (*sa_handler)();     { SIG_DFL,SIG_IGN,address} */
    /*           sigset_t   sa_mask;           */
    /*           int        sa_flags;          */
    /*      } sigaction                        */
    
    int counter,was_siged=0;
    pid_t mypid;
    
    void myhandler1(int sig, int code, struct sigcontext *spc);
    void myhandler2(int sig, int code, struct sigcontext *spc);
    void myhandler3(int sig, int code, struct sigcontext *spc);
    
    main (int argc, char * argv[])
    {
        struct sigaction act,oact;
        sigset_t  myset,oldset,pset;
    
        mypid = getpid();
        printf ("Starting process %d \n",mypid);
    
        act.sa_handler = SIG_IGN;
    /* Do not need to set the mask in act.sa_mask, since it is only used
    		if signals are caught */
        if (sigaction(SIGHUP,&act,&oact)) {
    	    perror("Could not set signal handler.\n");
        }
    
        act.sa_handler = &myhandler1;
    /* Fill the mask in act.sa_mask */
        sigfillset(&(act.sa_mask));
    /* Install myhandler1 as handler for SIGUSR2 and block all signals
    	during handling */
        if (sigaction(SIGUSR2,&act,&oact)) {
    	    perror("Could not set signal handler.\n");
        }
    
        act.sa_handler = &myhandler2;
        if (sigaction(SIGINT,&act,&oact)) {
    	    perror("Could not set signal handler. \n");
        }
    
    
    /* this is a section of code where I don't want any signals */
    
        sigfillset(&myset);
    /* Set mask to myset which is full to block all signals - store original
    			mask in oldset */
        sigprocmask(SIG_SETMASK,&myset,&oldset);
    
        /* do the critical stuff */
         printf ("I'm gonna take a nap go away. \n");
         sleep(5);
         printf ("That was a nice nap. I'm back.\n");
    
    /* Store the pending signals in pset */
        sigpending(&pset);
    /* Test if SIGINT is one of the pending signals - if so set the
    	handler to myhandler3, reset the mask to unblock SIGINT.
    	If SIGINT occured it will be handled now by myhandler3. */
        if (sigismember(&pset,SIGINT)) {
            act.sa_handler = &myhandler3;
            if (sigaction(SIGINT,&act,&oact)) {
        	    perror("Could not set signal handler.\n");
            }
    	sigdelset(&myset,SIGINT);
    	sigprocmask(SIG_SETMASK,&myset,NULL);
        }
    /* Restore the old action for SIGINT  and reset the mask to the old 
    	mask */
        if (sigaction(SIGINT,&oact,NULL)) {
            perror("Could not set signal handler.\n");
        }
        sigprocmask(SIG_SETMASK,&oldset,NULL);
    
    
    /* end of critical section */
    
        printf ("Setting the counter to 0 \n");
        counter = 0;
        while (1) {
           if (was_siged) {
               printf("Signal processed, counter : %d\n",counter);
               was_siged = 0;
           }
           counter++;
        }
    }
    
    void myhandler1(int sig, int code, struct sigcontext *spc)
    {
         static int count=0;
    
         printf("Caught the SIGUSR2 signal %d COUNTER is: %d \n",sig,counter);
    
    /* First time it gets called, it calls itself to show the effect of
    	recieving a SIGUSR2 while processing a SIGUSR2  */
    
         if (count == 0) {
    	 count++;
             printf ("Calling kill with sig SIGUSR2 \n");
             kill(mypid,SIGUSR2);
             printf ("Done Calling kill with sig SIGUSR2 \n");
         }
         was_siged = 1;
    }
    
    void myhandler2(int sig, int code, struct sigcontext *spc)
    {
         printf("Caught the SIGINT signal %d COUNTER is: %d \n",sig,counter);
         exit(0);
    }
    
    void myhandler3(int sig, int code, struct sigcontext *spc)
    {
         printf("You typed ^C while I was sleeping,  GO AWAY.\n",sig,counter);
    }
    

    Handling Signals in Perl

    An example of handling signals in Perl.

    #!/usr/local/bin/perl
    
    sub handler{
       local ($signal) = @_;
    
       print "The $signal was caught  \n";
       $SIG{'USR1'} = 'handler';
    }
    
    # the signal array is an associative array %SIG
    
    print "The process id is $$\n";
    # ignore the HUP signal
    $SIG{'HUP'} = 'IGNORE';
    
    # set the action for  SIGBUS to default.
    $SIG{'BUS'} = 'DEFAULT';
    
    # set usr1 handler to be handler.
    
    $SIG{'USR1'} = 'handler';
    
    while (1) {
       $count++;
    }
    

    Handling Signals in the Bourne Shell

    An example of handling signals in sh.

    #!/bin/sh
    
    echo "the pid is $$"
    
    # trap [cmd list] signal
    
    trap "echo a sigusr1 was typed" 16
    
    # trap [cmd list] 0 will execute when the shell is exited.
    
    trap "echo so long and thanks for all the fish" 0 1
    
    echo "Here is a list of commands associated with the signals"
    
    trap
    
    #trap "echo the man page says this causes an error " 11
    
    i=1
    
    while true 
    do
    i=`expr $i + 1`
    done
    

    Using Signals for Timeouts



    Paul A. Farrell
    Mon May 15 20:45:45 EDT 1995