Add Book to My BookshelfPurchase This Book Online

Chapter 10 - Signals

UNIX Systems Programming for SVR4
David A. Curry
 Copyright © 1996 O'Reilly & Associates, Inc.

Basic Signal Handling
In this section, we describe the basics of signal handling in terms of the oldest and simplest signal interface. The functions described in this section are available in all versions of UNIX, and are adequate for most uses.
Sending Signals
To send a signal to a process, use the kill function:
    #include <sys/types.h>
    #include <signal.h>
    int kill(pid_t pid, int sig);
The pid parameter specifies the process or group of processes to send the signal to, and the sig parameter identifies the signal to be sent. If sig is 0, then error checking is performed, but no signal is delivered. Use this to check the validity of pid.
Unless the sending process has an effective user ID of superuser, the real or effective user ID of the sending process must match the real or saved user ID of the receiving process(es). The only exception to this rule is SIGCONT, which may be sent to any process with the same session ID as the sending process (see Chapter 11, Processes).
The pid parameter has a number of interpretations:
 If pid is greater than 0, sig will be sent to the process whose process ID is equal to pid.
 If pid is negative but not equal to -1, sig will be sent to all processes whose process group ID (see Chapter 11, Processes) is equal to the absolute value of pid and for which the process has permission to send a signal.
 If pid is equal to 0, sig will be sent to all processes whose process group ID is equal to that of the sender, except for special system processes (the scheduler, page daemon, filesystem flusher, and initialization process).
 If pid is equal to -1 and the effective user ID of the sending process is not superuser, sig will be sent to all processes (except special system processes) whose real user ID is equal to the effective user ID of the sender.
 If pid is equal to -1 and the effective user ID of the sending process is superuser, sig will be sent to all processes in the system except special system processes.
Upon successful delivery of the signal, kill returns 0. If an error occurs, -1 is returned and the reason for failure is placed in the external integer errno.
ANSI C defines another, not very useful, function for sending signals:
    #include <signal.h>
    int raise(int sig);
Because the ANSI C standard does not recognize multiple processes, raise does not accept a pid argument. When called, raise sends the signal specified in sig to the calling process.
Waiting for Signals
Sometimes, a process wants to stop processing until a signal is received. For example, it might want to wait until a specified amount of time has passed, or until data becomes available on a file descriptor. To do this, use the pause function:
    #include <unistd.h>
    int pause(void);
The pause function simply suspends the calling process until it receives a signal. The signal must be one that is not currently blocked or ignored by the calling process. If the signal causes termination of the calling process, pause does not return (because the process exits). If the signal is caught by the calling process and control is returned from the signal handling function, pause returns -1 and errno is set to EINTR (interrupted system call). Execution of the process then continues from the point of suspension.
Printing Signal Information
There are two functions for printing signal information, similar to perror and strerror:
    #include <siginfo.h>
    void psignal(int sig, const char *s);
    #include <string.h>
    char *strsignal(int sig);
The psignal function prints the message contained in s, followed by a colon, followed by a string identifying the signal whose number is contained in sig, on the standard error output. The strsignal function returns a character string describing the signal contained in sig; this string is the same one printed by psignal.
The psignal function is not available in HP-UX 10.x. An example of how to implement it is shown in the on-line example programs. The strsignal function is not available in HP-UX 10.x or IRIX 5.x.
Handling Signals
The basic function for changing a signal's disposition is called signal, and is declared as follows:
    #include <signal.h>
    void (*signal(int sig, void (*disp)(int)))(int);
This rather confusing prototype says that signal accepts two arguments, and returns a pointer to a function that returns nothing (void). The first argument, sig, is an integer, and represents the signal whose disposition is to be changed. The second argument, disp, is a pointer to a function that takes a single integer argument and returns nothing (void). This function is the signal handler for sig; whenever sig is received, the disp function will be called with sig as its argument (this allows a single handler function to handle multiple signals). The return value from signal is a pointer to the previous signal handler function.
In addition to the address of a function, the disp parameter can be given one of the following values:
SIG_IGN
Sets the signal's disposition to ignore all future occurrences of sig will be ignored.
SIG_DFL
Sets the signal's disposition to the default disposition; any signal handler that was in place for this signal is discarded.
Example 10-1 shows a small program that catches theSIGUSR1 andSIGUSR2 signals, waits for them to arrive, and prints a message when they are received.
Example 10-1:  signal1
#include <signal.h>
#include <stdio.h>
void handler(int);
int
main(void)
{
    /*
     * Send SIGUSR1 and SIGUSR2 to the handler function.
     */
    if (signal(SIGUSR1, handler) == SIG_ERR) {
        fprintf(stderr, "cannot set handler for SIGUSR1\n");
        exit(1);
    }
    if (signal(SIGUSR2, handler) == SIG_ERR) {
        fprintf(stderr, "cannot set handler for SIGUSR2\n");
        exit(1);
    }
    /*
     * Now wait for signals to arrive.
     */
    for (;;)
        pause();
}
/*
* handler - handle a signal.
*/
void
handler(int sig)
{
    /*
     * Print out what we received.
     */
    psignal(sig, "Received signal");
}
    % signal1 &
    [1] 12345
    % kill -USR1 12345
    Received signal: Signal User 1
    % kill -USR2 12345
    Received signal: Signal User 2
    % kill 12345
    [1] + Terminated     signal1
The last kill command sends SIGTERM to the process; since it does not catch this signal and the default disposition is to terminate the process, it exits.

Previous SectionNext Section
Books24x7.com, Inc © 2000 –  Feedback