Introduction
Signals are a notification mechanism among processes, they can be either termination or warning signals, that allow process coordination and monitoring
Objectives
- Explain what signals are and how they are used
- Know the different signals and types of signals available in Linux
- Use kill, killall and pkill to send signals from the command line
What signals are
They are a inter process communication (IPC) mechanism used to notify process about asynchronous events (or exceptions).
The process that receives the signal may
- Not expect the event to occur
- Expect the event, but not know when it is most likely to occur
For example if a user decides to terminate a program, it could send a termination signal to the process through the kernel in order to kill the process.
There are two paths by which signals are sent to a process
- From the kernel to the process [for an exception or programming error]
- From the process to the kernel
Signals can only be sent between processes owned by the same user or from a process owned by the superuser to any process.
When a process receives a signal it will handle such signal in accordance to its code, however there are two types of signals that can not be handled and will always terminate the program
- SIGKILL
- SIGSTOP
Types of signals
There are several types of signals, generally signals handle two things
- Exceptions detected by hardware [such as an illegal memory reference]
- Exceptions generated by the environment [such as the premature death of a process from the user's terminal]
To see a list of the signals in Linux, along with their numbers do :
$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
Kill
A process cannot send a signal directly to other process, it myst ask the kernel to send the signal by executing a system call. Users (including the superuser) can send signals to other processes from the command line or scripts by using kill command
Sample
By default if no parameter is specified the signal type is SIGTERM (15), this will not termintate the process allowing the process to perform the close operations needed to terminate.
$ kill 1991
If the -9 parameter is specified, the process will terminate immediately
$ kill -9 1991
Other way to express the -9 paramenter is by using SIGKILL
$ kill -SIGKILL 1991
The name kill is not really apropiated since this command can send any type of signals to the processes even totally benign informative ones.
killall and pkill
killall command kills all processes with a given name, assuming the user has sufficient privilege. It uses a command name rather than a process ID, and can be done as in
$ killall bash $ killall -9 bash $ killall -SIGKILL bash
pkill sends a signal to a process using selection criteria
$ pkill [-signal] [options] [pattern]
for example
$ pkill -u libby foobar
Will kill all libby's process with a name of foobar.
The next command makes rsyslog reread its configuration file
$ pkill -HUP rsyslogd
Lab 21.1: Examining Signal Priorities and Execution
We give you a C program that includes a signal handler that can handle any signal. The handler avoids making any system calls (such as those that might occur while doing I/O).
You will need to compile it and run it as in:
$ gcc -o signals signals.c $ ./signals
/* * Examining Signal Priorities and Execution. * * The code herein is: Copyright the Linux Foundation, 2014 * Author: J. Cooperstein * * This Copyright is retained for the purpose of protecting free * redistribution of source. * * This code is distributed under Version 2 of the GNU General Public * License, which you should have received with the source. * @*/ #include <stdio.h> #include <unistd.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #define NUMSIGS 64 /* prototypes of locally-defined signal handlers */ void (sig_handler) (int); int sig_count[NUMSIGS + 1]; /* counter for signals received */ volatile static int line = 0; volatile int signumbuf[6400], sigcountbuf[6400]; int main(int argc, char *argv[]) { sigset_t sigmask_new, sigmask_old; struct sigaction sigact, oldact; int signum, rc, i; pid_t pid; pid = getpid(); /* block all possible signals */ rc = sigfillset(&sigmask_new); rc = sigprocmask(SIG_SETMASK, &sigmask_new, &sigmask_old); /* Assign values to members of sigaction structures */ memset(&sigact, 0, sizeof(struct sigaction)); sigact.sa_handler = sig_handler; /* we use a pointer to a handler */ sigact.sa_flags = 0; /* no flags */ /* VERY IMPORTANT */ sigact.sa_mask = sigmask_new; /* block signals in the handler itself */ /* * Now, use sigaction to create references to local signal * handlers * and raise the signal to myself */ printf ("\nInstalling signal handler and Raising signal for signal number:\n\n"); for (signum = 1; signum <= NUMSIGS; signum++) { if (signum == SIGKILL || signum == SIGSTOP || signum == 32 || signum == 33) { printf(" --"); continue; } sigaction(signum, &sigact, &oldact); /* send the signal 3 times! */ rc = raise(signum); rc = raise(signum); rc = raise(signum); if (rc) { printf("Failed on Signal %d\n", signum); } else { printf("%4d", signum); if (signum % 16 == 0) printf("\n"); } } fflush(stdout); /* restore original mask */ rc = sigprocmask(SIG_SETMASK, &sigmask_old, NULL); printf("\nSignal Number(Times Processed)\n"); printf("--------------------------------------------\n"); for (i = 1; i <= NUMSIGS; i++) { printf("%4d:%3d ", i, sig_count[i]); if (i % 8 == 0) printf("\n"); } printf("\n"); printf("\nHistory: Signal Number(Count Processed)\n"); printf("--------------------------------------------\n"); for (i = 0; i < line; i++) { if (i % 8 == 0) printf("\n"); printf("%4d(%1d)", signumbuf[i], sigcountbuf[i]); } printf("\n"); exit(EXIT_SUCCESS); } void sig_handler(int sig) { sig_count[sig]++; signumbuf[line] = sig; sigcountbuf[line] = sig_count[sig]; line++; }
When run, the program:
- Does not send the signals SIGKILL or SIGSTOP, which can not be handled and will always terminate a program.
- Stores the sequence of signals as they come in, and updates a counter array for each signal that indicates how many times the signal has been handled.
- Begins by suspending processing of all signals and then installs a new set of signal handlers for all signals.
- Sends every possible signal to itself multiple times and then unblocks signal handling and the queued up signal handlers will be called.
- Prints out statistics including:
- The total number of times each signal was received.
- The order in which the signals were received, noting each time the total number of times that signal had been received up to that point.
Note the following:
- If more than one of a given signal is raised while the process has blocked it, does the process receive it multiple times? Does the behavior of real time signals differ from normal signals?
- Are all signals received by the process, or are some handled before they reach it?
- What order are the signals received in?
One signal, SIGCONT (18 on x86) may not get through; can you figure out why?
Note:
On some Linux distributions signals 32 and 33 can not be blocked and will cause the program to fail. Even though system header files indicate SIGRTMIN=32, the command kill -l indicates SIGRTMIN=34. Note that POSIX says one should use signal names, not numbers, which are allowed to be completely implementation dependent. You should generally avoid sending these signals.