Previous Page Next Page

18.5. Signals

A signal sends a message to a process and normally causes the process to terminate, usually due to some unexpected event, such as illegal division by zero, a segmentation violation, a bus error, or a power failure. The kernel also uses signals as timers, for example, to send an alarm signal to a process. The user sends signals when he hits the BREAK, DELETE, QUIT, or STOP keys.

The kernel recognizes 31 different signals, listed in /usr/include/signal.h. You can get a list of signals by simply typing kill -l at the UNIX prompt. (See Table 18.13.)

Table 18.13. Signals (BSD)[*]
NameNumberDefaultDescription
SIGHUP1TerminateHangup
SIGINT2InterruptInterrupt
SIGQUIT3TerminateQuit/produces core file
SIGILL4TerminateTerminate


[*] This is a partial listing of the signals.

Catching Signals

Signals are asynchronous events; that is, the process doesn't know when a signal will arrive. Programmatically you can ignore certain signals coming into your process or set up a signal handler to execute a subroutine when the signal arrives. In Perl scripts, any signals you specifically want to handle are set in the %SIG associative array. If a signal is ignored, it will be ignored after fork or exec function calls.

A signal may be ignored or handled for a segment of your program and then reset to its default behavior. See Example 18.72.

Format

$SIG{'signal'};

Example 18.72.

(The Script)
    #!/bin/perl
1   sub handler{
2       local($sig) = @_;     # First argument is signal name
3       print "Caught SIG$sig--shutting down\n";
4       exit(1);
    }
5   $SIG{'INT'} = 'handler'; # Catch <Ctrl>-c
6   $SIG{'HUP'}='IGNORE';
7   print "Here I am!\n";
    sleep(10);
8   $SIG{'INT'}='DEFAULT';[a]

(Output)
7   Here I am
        < <Ctrl>-c is pressed while the process sleeps >
3   Caught SIGINT--shutting down

Explanation

  1. The subroutine called handler is defined.

  2. The local function sets the first argument, the signal name, to the scalar $sig.

  3. If the signal arrives, the handler routine is executed and this statement is printed.

  4. The program exits with a value of 1, indicating that something went wrong.

  5. A value for the $SIG associative array is set. The key is the name of the signal without the SIG prefix. The value is the name of the subroutine that will be called. If <Ctrl>-c, the interrupt key, is pressed during the run of the program, the handler routine is called.

  6. IGNORE will ignore the hangup signal.

  7. The print statement is executed and the process sleeps for 10 seconds. If the signal <Ctrl>-c arrives, the signal handler routine is called.

  8. The SIGINT signal is reset to its default state, which is to terminate the process when <Ctrl>-c is pressed.

[a] Wall, L., and Schwartz, R. L., Programming Perl, 2nd ed., O'Reilly & Associates:Sebastopol, CA, 1998.


Sending Signals to Processes—The kill Function

If you want to send a signal to a process or list of processes, the kill function is used. The first element of the list is the signal. The signal is a numeric value or a signal name if quoted. The function returns the number of processes that received the signal successfully. A process group is killed if the signal number is negative. You must own a process to kill it; that is, the effective uid and real uid must be the same for the process sending the kill signal and the process receiving the kill signal.

For complex signal handling, see the POSIX module in the Perl standard library.

Format

kill(LIST);
kill LIST;

Example 18.73.

1   $ sleep 100&
2   $ jobs -l
    [1] + 6505 Running sleep 100&
3   $ perl -e 'kill 9, 6505'
    [1] Killed sleep 100

Explanation

  1. At the UNIX shell prompt, the sleep command is executed in the background. The sleep command causes the shell to pause for 100 seconds.

  2. The jobs command lists the processes running in the background. The sleep process pid is 6505.

  3. Perl is executed at the command line. The kill function takes two arguments. The first, signal 9, guarantees that the process will be terminated. The second argument is the pid of the sleep process.


The alarm Function

The alarm function tells the kernel to send a SIGALARM signal to the calling process after some number of seconds. Only one alarm can be in effect at a time. If you call alarm and an alarm is already in effect, the previous value is overwritten.

Format

alarm (SECONDS);
alarm SECONDS;

Example 18.74.

(The Script)
1   alarm(1);
2   print "In a Forever Loop!";
3   for (; ;){ printf "Counting...%d\n", $x++;}

(Output)
2   In a Forever Loop!
3   Counting...0
    Counting...1
    Counting...2
    Counting...3
    Counting...4
        ...
    Counting...294
    Counting...295
4   Alarm Clock

Explanation

  1. A SIGALARM signal will be sent to this process after 1 second.

  2. This statement is printed.

  3. The loop starts. We wait for 1 second. The resolution on the actual second may be off. The syscall function can be used to call other functions, for example, setitimer (2) and getitimer (2), with better timing resolution.

  4. When the alarm goes off, the message Alarm Clock is printed by the function.


The sleep Function

The sleep function causes the process to pause for a number of seconds or forever if a number of seconds is not specified. It returns the number of seconds that the process slept. You can use the alarm function to interrupt the sleep.

Format

sleep(SECONDS);
sleep SECONDS;
sleep;

Example 18.75.

(The Script)
    #!/bin/perl
1   $|=1        # flush output buffer
2   alarm(5);
    print "Taking a snooze...\n";
3   sleep 100;
4   print "\07 Wake up now.!\n";

(Output)
2   Taking a snooze...   # Program pauses now for 5 seconds
4   (Beep) Wake up now.

Explanation

  1. The $| variable forces the output buffer to be flushed after it writes and prints.

  2. The alarm function tells the kernel to send a SIGALARM signal to the process in 5 seconds.

  3. The process goes to sleep for 100 seconds or until a signal is sent to it.

  4. The \07 causes a beep to sound before the statement Wake up now!


Attention, Windows Users!

For those using ActivePerl on Win32 systems, the following functions have not been implemented. Primary among these is alarm(), which is used in a few Perl modules. Because they're missing in ActivePerl, you can't use those modules. Here is a complete list of unimplemented functions:

Functions for processes and process groups:

   alarm(), fork(), getpgrp(), getppid(), getpriority(), setpgrp(),
   setpriority()

Functions for fetching user and group info:

   endgrent(), endpwent(), getgrent(), getgrgid(), getgrnam(),
   getpwent(), getpwnam(), getpwuid(), setgrent(), setpwent()

System V interprocess communication functions:

   msgctl(), msgget(), msgrcv(), msgsnd(), semctl(), semget(),
   semop(), shmctl(), shmget(), shmread(), shmwrite()

Functions for filehandles, files, or directories:

   link(), symlink(), chroot()

Input and output functions:

   syscall()

Functions for fetching network info:

   getnetbyname(), getnetbyaddr(), getnetent(), getprotoent(),
   getservent(), sethostent(), setnetent(), setprotoent(),
   setservent(), endhostent(), endnetent(), endprotoent(),
   endservent(), socketpair()

See the perlport and perlwin32 documentation pages for more information on the portability of built-in functions in ActivePerl.

Previous Page Next Page