- Signal handlers
- Working with signals
- Blocking operations (
Signals are asynchronous notifications sent to processes by the kernel, potentially in response to a hardware exception or interrupt. The kernel interrupts the flow of execution of a process during any non-atomic instruction to deliver the signal.
Signals are not queued. Processes have binary flags to represent whether a signal is pending. When a signal is delivered, the corresponding binary flag will be set to true. The signal will be delivered as soon as the signal is not blocked and the binary flag will be reset to false. If a signal is delivered multiple times, the corresponding binary flag is set to true, and the signal is delivered once unless the binary flag is set to false before the new instance of the signal is delivered.
Signal handlers are only executed when transitioning from kernel mode to user mode. The kernel checks the pending signals when deciding to schedule a process to run. When delivering a signal, the kernel stores the current execution context into the user-space stack, creates a stack frame for the signal handler, and jumps into the signal handler in user mode. After a signal handler executes, the kernel takes over control in order to restore the execution context.
A process may specify signal handlers to respond to, ignore, or block
signals other than
SIGSTOP. If not handled, the default signal
handlers are executed (documented in
Programs may setup signal handlers using
sigaction(2), or its easier-to-use
signal(3). The handler functions receive the signal number as an
Signals may be delivered while a signal handler is running. For this reason, it is recommended for signal handlers to be reentrant (it can safely be executed by multiple threads in parallel) and/or not be interruptible by signal handlers.
Linux maintains a list of “async-signal-safe” functions that are safe to use in
signal handlers in
POSIX defines an integer type
sig_atomic_t that is safe to use as a global
variable shared between a program and its signal handlers. Read and write to
sig_atomic_t variables are atomic operations, but
-- are not. It
is recommended to declare
sig_atomic_t variables as
volatile to prevent
Signal handlers typically use the process’ stack, but they can be configured to
use a custom stack with
sigaltstack(2). This can be useful when handling the
SIGSEGV signal, which can occur when the process stack space is exhausted.
A signal may be delivered while its own signal handler is running. The signal
that triggered the handler is blocked by default when the handler runs, unless
SA_NODEFER is set, in which case the new instance of the signal will be
set to pending and will be delivered once the running signal handler exits.
A process may send a signal along with a piece of data (an integer or a
pointer) by using
sigqueue(3). The corresponding handler can access this data
if it was setup with the
SA_SIGINFO flag of
Working with signals
Processes may send signals using
kill(2). A process only has permission to
send a signal if the real or effective user ID match, or the user has
super-user privileges. As an exception, the
SIGCONT can always be sent to any
descendant of the process.
kill(2) will fail if the sender is configured to
ignore the signal.
kill(2) function allows a process to send a signal to a specific process
(ignoring its descendants), to all the processes that belong to the sender’s
process group ID, or (given super-user privileges) to all the processes
excluding system processes.
The shell sends interrup signals, like
SIGINT, to the foregroung process group.
Blocking (masking) signals
Signals, other than
SIGSTOP, can be blocked with
sigprocmask(2). Blocked signals are delivered when the signal is unblocked.
The list of pending signals can be obtained with
signals is useful to prevent interrupts during critical code paths. Signal
masks are per thread, and not per process.
SIGCONTsignal can’t be blocked on Linux
sigaction(2) function accepts a set of signals that must be blocked when
executing a particular signal handler. Also, the signal that executed the
current signal handler will be blocked unless the
SA_NODEFER flag is set.
If a signal handler is updated while a signal is pending, then the updated handler will be executed. The operating system only checks how a process wants to react to a handler when delivering the signal, and not when setting the signal’s binary flag.
Signals, other than
SIGSTOP, can be ignored using
Processes may reset a signal handler to its default by using
sigaction(2) function also supports a
to implement one-shot signal handlers where the handler is reset after the
first handler execution.
Waiting for signals
A process may wait for a signal to occur with the
sigtimedwait(2) (which supports a timeout argument) functions.
Pausing and resuming processes
A process may be paused with
SIGSTOP (sent when pressing
Ctrl-Z on a shell)
and then resumed with
Terminating a process
There are many signals to terminate a process.
SIGTERM allows a process to
SIGKILL inconditionally aborts the process and can be
used as a last resort.
SIGQUIT terminates a process, potentially creating a
A forked process inherits the signal mask and all signal handlers. The
execve(2) resets all signal handlers but keeps the set of ignored and blocked
A parent process receives
SIGCHLD when a child exits, unless the
SA_NOCLDSTOP flag of
sigaction(2) is set. Handling
SIGCHLD is not a
reliable way to wait for more than one children to exit, as multiple children
might exit while
SIGCHLD is being handled, but
SIGCHLD would only be
If a process has more than one thread, then the signal handler is sent to only
one of its threads. This decision is implementation-specific. Programs may send
a signal to a specific thread using
Some signals generated a result of an specific instruction, such as
SIGFPE, will always be sent to the thread that executed such instruction.
Blocking operations (
If a signal is delivered while a blocking system call (like
running, then the system call will fail with
EINTR. The calling program may
EINTR by manually restarting the system call. Affected system calls
may also be automatically restarted after signal interruption if the signal is
setup with the
The full list of
affected system calls is documented in
The affected system calls include open(2), read(2), write(2), sendto(2), recvfrom(2), sendmsg(2) and recvmsg(2)