COMP421
Unix Environment for Programmers
Lecture 17: Signals____________________________________________
Jeff Wiegley, Ph.D.
Computer Science
jeffw@csun.edu
10/17/2005
‘‘Ships that pass in the night, and speak each other in passing, only a signal shown, and a distant voice in the darkness; So on the ocean of life, we pass and speak one another, only a look and a voice, then darkness again and a silence.’’ – Henry Wadsworth Longfellow |
1
Signals:________________________________________________
“Signals” present a simple mechanism for processes to communicate with each other.
They are software interrupts.
They function like interrupt vectors (which will be familiar to those with some background in electrical engineering or micro-controllers.)
2
Signal names._________________________________________
Every signal has a name (which maps to a number). Common names are SIGHUP, SIGKILL, SIGTERM and SIGUSR1
There is no difference between signals. They can all do the same thing.1
The variety allows a program to tailer its behavior depending on which signal it received.
3
What causes signals to be sent:____________________
Signals are caused by a variety of events:
4
What can we do with signals:______________________
If we change the handler then, when a matching signal is received, the program will immediately interrupt what is doing and run the signal handler function instead.
When the signal handler returns the programs picks up where it left off when it was interrupted.
5
Changing the handler:_______________________________
The simplest method for changing the handler is:
#include <signal.h>
typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler); |
Which is basically a simple function that takes two arguments:
6
An example:__________________________________________
#include <signal.h>
#include <stdio.h> void myhandler(int signo) { fprintf(stderr,"Damn it! I refuse to quit!!"); } void updateconf(int signo) { fprintf(stderr,"reloading configuration file"); } int main(int argc, char *argv[]) { signal(SIGINT, myhandler); signal(SIGHUP, updateconf); while (1); /* infinite loop */ } |
7
Exec and signals:_____________________________________
When exec() is called to change a process. (such as after fork()) exec does the following:
8
Problems with earlier systems:_____________________
In early systems, signals where “unreliable”.
This was due to the fact the signal handler was reset to SIG IGN each time the signal was received.
Classic solution was to re-enable the signal handler as the first or last step in the signal handling function itself.
This meant that there was a small window of time after a first occurrence of a signal was received when a second instance of the signal could occur before the signal handler was reset and the default handler would execute. For signals such as SIGTERM this meant the process died when it shouldn’t have. (The default action for SIGTERM is to kill the process.)
9
Another problem:____________________________________
There are times when you want to ignore a signal (during a critical calculation, for instance)
But you still want to know that the signal occurred so that you can process it after the critical computation is completed.
Early systems only allowed you to suspend signals by simply ignoring them. This has no memory that signals ever occurred and therefore aren’t suitable to solve this problem.
10
Signals can interrupt System calls:________________
Remember that read() is a blocking system call?3
Q: Well guess what happens if the process receives a signal while read() is blocked?
A: read() unblocks! (and more specifically returns -1 indicating that an error occurred.)
So, as programmers we have to be very careful when using system calls in conjunction with signals that we very carefully check the return status of the system call.
In this case, read() returned -1 AND set errno to EINTR. So before assuming that read() failed because of some fatal error we have to check errno first.
11
WARNING!!!!:________________________________________
Signal handler should not make use of any NON-reentrant functions.
This includes malloc() and free(), all system calls that utilize these and all other non-reentrant system calls.
Figure 10.4 of the book lists the known reentrant system calls that are safe to use in signal handlers.
12
Some signal functions:_______________________________
There is a lot of code based on earlier, unreliable, signals.
POSIX provides a suite of functions that implement reliable signals.
13
Signal sets:____________________________________________
POSIX provides a suite of functions that implement reliable signals.
First we need to know about signal sets:
14
Reliable Signals:______________________________________
15
Blocking signals:_____________________________________
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
how is one of SIG_BLOCK, SIG_UNBLOCK or SIG_SETMASK.
if oldset is not NULL then the previous signal mask is stored in oldset.
if set is not NULL then the set of signals specified is either blocked or unblocked. (or if how==SIG_SETMASK then the set of block signals is set equal to set.
Unblocking a signal causes any pending signals to be delivered. However, multiple generations of a signal while blocked do not queue up. When unblocked only a single signal is delivered.4
16
Checking for pending signals:______________________
int sigpending(sigset_t *set);
The set returned consists of the signals that have been raised while blocked.
17
Changing signal handlers:___________________________
int sigaction(int signum,
const struct sigaction *act,
struct sigaction *oldact)
struct sigaction {
void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); } |
sa_mask provides a set of signals which are blocked during execution of the sa_handler.
sa_flags can be used to modify behavior of the signal handler. SA_RESETHAND, for instance, will cause the signal’s handler to be the default action after the handler runs (=early implementations).
18
Conclusion.___________________________________________
In conclusion, the reliable signal routines should be used for all new applications.
19