Signals are the interrupts. They are a way of providing asynchronous events. For example a user typing ctrl-c on terminal to stop a program. Most of the programs need to handle signals. Every signal has a name like SIGxxx. For example : SIGALRM is the alarm signal that is generated when the timer set by the alarm function goes off.
On Linux, different signals are defined in <bits/signum.h>.
The are various scenarios in which is signal is generated :
- When a user press a terminal key (like ctrl-c). This type of signal are known as terminal generated signals and normally cause the interrupt signal SIGINT to be generated. SO now we know how/why our programs stop when we press ctrl-c.
- Whenever hardware exceptions occur. Like whenever divide by zero, illegal memory access etc occur. These type of exceptions are usually detected by the hardware and then the hardware notifies the kernel. Its the kernel that notifies the process which generated this exception through a signal known as :SIGSERV.
- From inside a process, kill() function allows you to pass any signal to other process provided that you are the owner of that process or you are the superuser.
- Then there is kill command through which we can kill the processes in our system. Its just an interface to the kill() function so the conditions for killing a process remain the same(as described in point above).
- Scenarios like in which some software condition occurs like alarm set by the process goes off, or when a process tries to write to a pipe after the reader has been terminated etc.
Going a bit deeper
Whenever a signal is generated, the process has to tell the kernel what to do with this signal. So in all three kind of options are available for a process :
- Catch a Signal: In order to make this happen, we tell the kernel to call a function of ours when a signal is generated. In that particular function, we can do our stuff that we want to do when a signal is generated. For example, If the SIGCHLD signal is caught, it means that a child process has terminated, so the signal-catching function can call waitpid to fetch the child's process ID and termination status. Similarly a SIGTERM signal which is sent when we issue kill command or kill function. Please note here that the two signals SIGKILL and SIGSTOP cannot be caught.
- Ignore a signal: Well, this action works for most of the signals except the two signals SIGKILL and SIGSTOP. The reason is that these two signals provide kernel or superuser a sure-shot way of stopping any process.Please note here that if you ignore signals generated through an exception such that 'divide by zero' etc then the behavior of the process is undefined.
- Let the default action apply: Every signal has a default action. For most of the signals, default action is to terminate the process.
Following is a list of signals and their description for your reference :
SIGABRT abnormal termination (abort)
SIGALRM timer expired (alarm )
SIGBUS hardware fault
SIGCANCEL threads library internal use
SIGCHLD change in status of child
SIGCONT continue stopped process
SIGEMT hardware fault
SIGFPE arithmetic exception
SIGFREEZE checkpoint freeze
SIGILL illegal instruction
SIGINFO status request from keyboard
SIGINT terminal interrupt character
SIGIO asynchronous I/O
SIGIOT hardware fault
SIGLWP threads library internal use
SIGPIPE write to pipe with no readers
SIGPOLL pollable event (poll)
SIGPROF profiling time alarm (setitimer)
SIGPWR power fail/restart
SIGQUIT terminal quit character
SIGSEGV invalid memory reference
SIGSTKFLT co-processor stack fault
SIGSYS invalid system call
SIGTHAW checkpoint thaw
SIGTRAP hardware fault
SIGTSTP terminal stop character
SIGTTIN background read from control tty
SIGTTOU background write to control tty
SIGURG urgent condition (sockets)
SIGUSR1 user-defined signal
SIGUSR2 user-defined signal
SIGVTALRM virtual time alarm (setitimer)
SIGWAITING threads library internal use
SIGWINCH terminal window size change
SIGXCPU CPU limit exceeded (setrlimit)
SIGXFSZ file size limit exceeded (setrlimit)
SIGXRES resource control exceeded
The function used for implementing signals is :
void (*signal(int signo, void (*func )(int)))(int);
As it could be a bit difficult to decode this prototype, so lets start with its explanation :
The prototype states that, the function requires two arguments. The first argument is signo(an integer). The second argument is a function pointer that takes single integer and returns nothing. While the function itself returns function pointer whose return type is void.
I understand that the prototype could be still cryptic, lets try to ease out a level more by creating the following typedef :
typedef void Sigfunc(int);
Now, the prototype of the above function becomes :
Sigfunc *signal(int, Sigfunc *);
Now, I think its far more easy to understand.
The signo argument is just the name of the signal. The value of func is
- SIG_IGN : If we want to ignore the signal
- SIG_DFL: If we want default action to be applied
- Function pointer of a function to be called when the signal occurs.
When we specify the address of a function to be called when the signal occurs, we mean to "catch" the signal.
Lets consider the following code :
void sig_handler(int signo)
if (signo == SIGUSR1)
else if (signo == SIGUSR2)
printf("ERR : received signal %d\n", signo);
if (signal(SIGUSR1, sig_handler) == SIG_ERR)
printf("\ncan't catch SIGUSR1\n");
if (signal(SIGUSR2, sig_handler) == SIG_ERR)
printf("\ncan't catch SIGUSR2\n");
while(1) // Simulate a dummy wait
In the above program, we have created a sig_handler function which we have registered with kernel through signal function call for the signals SIGUSR1 and SIGUSR2. So the idea is that whenever a signal USR1 or USR2 from kill command is sent to this process, the function sig_handler should be called and we should be able to handle the signal cleanly. In this case we just print to stdout when a signal is received.
Lets run it :
Now, in some other terminal, find the PID of signal process and kill it using signal USR1.
$ ps -aef | grep signal
himanshu 5018 4659 0 08:27 pts/1 00:00:00 ./signal
himanshu 5043 4918 0 08:28 pts/2 00:00:00 grep --colour=auto signal
$ kill -USR1 5018
Now come to the same terminal where signal process was running and you will see that the process is not killed as it has handled the signal:
To Conclude, signals are un-avoidable part of system programming. Almost all kind of tools/utilities etc take care of signal handling and process them accordingly.