200 likes | 485 Views
Signals. Signal Concepts. Signals are software interrupts Used to handle asynchronous events Each signal is a positive integer, defined by standardized names All the signals start with SIG SIGKILL = 9 SIGTERM = 15 SIGCHLD = 17 SIGINT = 2. Signal Concepts.
E N D
Signal Concepts • Signals are software interrupts • Used to handle asynchronous events • Each signal is a positive integer, defined by standardized names • All the signals start with SIG • SIGKILL = 9 • SIGTERM = 15 • SIGCHLD = 17 • SIGINT = 2
Signal Concepts • Signals are defined in <signal.h> • man 7 signal for complete list of signals and their numeric values • kill –l for full list of signals on a system • 64 signals. The first 32 are traditional signals, the rest are for real time applications
Conditions That Can Generate Signals • Generated by terminal • ctrl-c, ctrl-\, ctrl-z etc • Hardware exceptions can generate signals • Division by zero, bad memory reference, etc • “kill” shell command: ex – kill pid • kill function callint kill(pid_t pid, int sig); • Software can generate signals • SIGALRM, SIGPIPE, etc • Page 292-298 has descriptions of each signal
Signal Dispositions • Ignore the signal • SIG_IGN • Note: SIGKILL and SIGSTOP can not be ignored • Catch the signal • Register a custom signal handler to be run when the process is sent the corresponding signal • Allow default action • SIG_DFL • All signals have a default action. See page 292 fig 10.1
Signal Function void (*signal(int signo, void (*func)(int)))(int); OR typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler); • signo is the signal number to handle • func defines how to handle the signal • SIG_IGN • SIG_DFL • Function pointer of a custom handler • Returns previous disposition if ok, or SIG_ERR on error
Unreliable Signals • In older versions of UNIX, signals could be lost and the process would never know • Processes had little control over signals. It could catch or ignore the signal • Sometimes we want to temporarily block signals and process them later to protect a critical section of code
Reentrant Functions • Reentrant functions can be interrupted at any point and resumed later without error • Reentrant functions are thread and signal safe • If the signal handler is reentrant and does not call exit then when it finishes, the process will continue where it was interrupted without error • Page 306 lists functions guaranteed by POSIX.1 to be reentrant
Reliable-Signal Terminology and Semantics • A signal is said to be generated or raised for a process when an event happens that causes the signal to occur • A signal is delivered to a process when it takes action based on that signal • During the time between generation and delivery, a signal is said to be pending • A process may block some signals using a signal mask that defines which signals are currently blocked for the process
kill and raise functions int kill(pid_t pid, int sig); int raise(int sig); • kill sends a signal to a process or group of processes • pid > 0 – send to process with PID = pid • pid = 0 – send to all processes with PGID = PGID of caller • pid < 0 – send to all processes with PGID = |pid| • To send signals to other processes, EUID must match • raise allows a process to send a signal to itself
alarm and pause unsigned int alarm(unsigned int seconds); • Sets a timer in clock seconds (not exact) • When time is up, SIGALRM is sent to the process. Default action is to terminate the process • Only 1 alarm per process • Returns • 0 if no previous alarm set, or if previous alarm had less than 1 second left • Number of seconds left before alarm • alarm(0) cancels any pending alarms
alarm and pause int pause(void); • Suspends a process until it receives a signal • Returns -1 with errno set to EINTR • Can use alarm and pause to put a process to sleep for a specified amount of time • Note: we must set the handler for SIGALRM before calling alarm or a race condition can occur that may result in program termination (default action for SIGALRM)
POSIX Signal APIs • A type is defined to hold a set of signals sigset_t • 5 functions to manipulate a signal set int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); int sigaddset(sigset_t *set, int signum); int sigdelset(sigset_t *set, int signum); int sigismember(const sigset_t *set, int signum);
sigprocmask function int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); • If oldset is not NULL, it points to the previous signal set for this process • If set is NULL, current mask is unchanged and how parameter is ignored • If set is not NULL, then how specifies how the current mask is modified by set • SIG_BLOCK - signals in set are added to mask • SIG_UNBLOCK – signals in set are removed • SIG_MASK – mask is replaced by set
sigaction function int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); struct sigaction { void (*sa_handler)(int); sigset_t sa_mask; int sa_flags; … }
sigaction function • sa_flags • SA_RESETHAND or SA_ONESHOT. Resets the handler to the default after it has been executed once • SA_RESTART. Restarts system calls if they were interrupted by this signal • See page 326 for full list of flags
sigpending function int sigpending(sigset_t *set); • Returns set of pending signals that are blocked for this process • Returns 0 if ok, -1 on error
sigsuspend function • Provides an atomic way to unblock a signal and then wait for it to occur int sigsuspend(const sigset_t *mask); • Sets the signal mask to mask and then suspends the processes until a signal occurs • Returns -1 with errno set to EINTR
abort function void abort(void); • Causes the process to terminate and generates a core file • Sends SIGABRT to the process. If the handler doesn’t terminate the process when it returns abort itself will
strsignal function char *strsignal(int sig); • Given a signal number, returns a string representation of it