Signals are interruptions that are generated by the software and give us a way of handling asynchronous events. Those interruptions can be generated by things outside the process (like Ctrl+C from the user in the terminal) or from errors inside the process (like a math error for dividing with 0).

There are 31 standard signals, numbered 1-31. Each signal is named as "SIG" followed by a suffix. Starting from version 2.2, the Linux kernel supports 33 different real-time signals. These have numbers 32-64 but programmers should instead use SIGRTMIN+n notation. Standard signals have specific purposes but the use of SIGUSR1 and SIGUSR2 can be defined by applications. Real-time signals are also defined by applications.

Number Name Default Action Description
1 SIGHUP Terminate Terminal line hangup or parent process terminated
2 SIGINT Terminate Interrupt from keyboard (ctrl-c)
3 SIGQUIT Terminate Quit from keyboard (ctrl-\)
4 SIGILL Terminate Illegal instruction
5 SIGTRAP Core Trace trap
6 SIGABRT Core Signal from abort function
7 SIGBUS Terminate Bus error
8 SIGFPE Core Floating-point exception
9 SIGKILL Terminate Kill program
10 SIGUSR1 Terminate User-defined signal 1
11 SIGSEGV Core Invalid memory reference (segfault)
12 SIGUSR2 Terminate User-defined signal 2
13 SIGPIPE Terminate Write in pipe with no reader
14 SIGALRM Terminate Timer signal from alarm function
15 SIGTERM Terminate Software termination signal
16 SIGSTKFLT Terminate Stack fault on coprocessor
17 SIGCHLD Ignore Child process has stopped or terminated
18 SIGCONT Ignore Continue process if stopped
19 SIGSTOP Stop Stop signal not from terminal
20 SIGTSTP Stop Stop signal from terminal (ctrl-z)
21 SIGTTIN Stop Background process read from terminal
22 SIGTTOU Stop Background process wrote to terminal
23 SIGURG Ignore Urgent condition on socket
24 SIGXCPU Terminate CPU time limit exceeded
25 SIGXFSZ Terminate File size limit exceeded
26 SIGVTALRM Terminate Virtual timer expired
27 SIGPROF Terminate Profiling timer expired
28 SIGWINCH Ignore Window size changed
29 SIGIO Terminate I/O now possible on a descriptor
30 SIGPWR Terminate Power failure
31 SIGSYS Terminate Bad system call

Signals can be delivered to a process at any time during its execution, launched by events like user actions, hardware exceptions, or even more inter-process communication.

Signals can interrupt the normal flow of a process and require the process to handle or respond to the signal appropriately.

Signals are delivered by the operating system to the target process.

When a signal is generated, the operating system identifies the target process based on its process ID (PID).

The operating system then interrupts the execution of the target process and delivers the signal by invoking the corresponding signal handler or performing the default action associated with the signal.

Signals can be delivered by various sources, including the user, hardware exceptions, or other processes involved in inter-process communication.

The delivery of signals involves coordination between the operating system and the target process.

The operating system is responsible for identifying the target process, interrupting its execution, and delivering the signal, while the process handles the signal by executing the corresponding signal handler or default action.

Here are some common default actions:

  • Termination Signals
    • SIGINT (Interrupt): The process is terminated. This signal is generated by pressing Ctrl+C.
  • Termination with Core Dump Signals
    A core dump is a file that contains a snapshot of a program's memory at the time of a crash or termination due to a critical error. It includes information about memory, registers, and program state.
    • SIGQUIT (Quit): The process is terminated. This signal is triggered by pressing Ctrl+\ on the keyboard. A core dump is generated.
    • SIGILL (Illegal Instruction): The process is terminated with a core dump, indicating an illegal instruction.
    • SIGABRT (Abort): The process is terminated with a core dump, usually when an internal error or inconsistency is detected.
    • SIGFPE (Floating-Point Exception): The process is terminated with a core dump when a floating-point arithmetic exception occurs, such as division by zero.
    • SIGSEGV (Segmentation Fault): The default action for this signal is to terminate the process and generate a core dump. It occurs when the program attempts to access a memory location that it is not allowed to access, such as accessing an invalid pointer or accessing memory that has not been allocated.
  • Ignored Signals
    • SIGCHLD (Child Status Changed): The signal is ignored, indicating that the process does not want to be notified when child processes terminate.
    • SIGURG (Urgent Condition on Socket): The signal is ignored, typically used for out-of-band data in socket communication.
  • Stop Signals
    • SIGSTOP (Stop): The process is stopped (paused) and can be resumed later using SIGCONT.
    • SIGTSTP (Terminal Stop): The process is stopped (paused) by the user, typically through the Ctrl+Z combination.
  • Continue Signal
    • SIGCONT (Continue): The process is resumed after being stopped or paused.

The purpose of signals is multifaceted and serves several important functions:

  • Notify processes about events or conditions
    • Example 1: for a user action, sending a SIGINT signal (Ctrl+C) to notify a process to terminate gracefully in response to a user interrupt.
    • Example 2: for a hardware exception, sending a SIGFPE signal, which indicates a floating-point arithmetic exception ( → division by zero).
  • Handle asynchronous events efficiently
    • Example: receiving a SIGALRM signal to handle a timer or alarm event, allowing the process to perform a specific action after a specified time interval.
  • Handle exceptional situations or errors
    • Example: catching a SIGSEGV signal (segmentation fault) to handle a memory access violation, enabling the process to log the error and gracefully recover or terminate.
  • Facilitate inter-process communication
    • Example: sending a SIGUSR1 signal from one process to another as a custom communication mechanism, indicating a request for specific actions or data exchange between the processes.
  • Enable graceful termination of processes
    • Example: receiving a SIGTERM signal to initiate a graceful termination process, allowing the process to perform cleanup tasks, release resources, and exit gracefully.
  • Allow for custom behavior in response to signals
    • Example: registering a signal handler for a custom signal, such as SIGUSR2, to define a specific action that the process should take when receiving that signal, tailored to the specific needs of the application.

To create a signal in C, you can use the kill() or raise() functions. To send a signal from one process to another process, you can use the kill() function. To send a signal to itself, a process can use the raise() function.

Here's an example of using kill() to send a SIGTERM signal to a process with a specific PID:

#include <sys/types.h>
#include <signal.h>

int main() 
{
    pid_t pid = 1234; /* Replace it with the target process ID */

    /* Send SIGTERM signal to the process */
    int result = kill(pid, SIGTERM);
    
    if (result == 0) 
    {
        printf("Signal successfully sent.\n");
    }
    else 
    {
        printf("Failed to send signal.\n");
    }
    
    return 0;
}

Here's an example of using raise() to send a SIGINT signal to the current process:

#include <signal.h>

int main() 
{
    /* Send SIGINT signal to the current process */
    raise(SIGINT);
    
    return 0;
}