Signal Processing
As of version 1.2.6rc1, the way in which the daemon processes received
signals changed. Signal handlers are notorious for introducing race
conditions[1]; it is a consequence of running code
asynchronously, as signal handlers do. The core code was significantly
changed to avoid the actual processing of signals so that such processing is
run synchronously. This means that a signal handler merely sets a bit in a
value, and exits swiftly, when a signal is delivered to the process. A call to
a core signal processing function,
pr_signals_handle()
,
is done frequently in order to act, synchronously, on any received signals.
This also means that signals do not, for the most part, interrupt the core
code. For example, a while()
loop that can potentially loop
endlessly, and which does not call pr_signals_handle()
, will
not be interrupted by most signals (SIGKILL
being an obvious
exception). Please keep this in mind when developing your module; feel
free to call pr_signals_handle()
often, especially if a
system or library call has been interrupted by a signal (i.e. the call
returns -1, and errno
is EINTR
, or when writing long
loops or recursive functions. Here's an example that can be seen often
in the core code:
while (syscall() < 0) { if (errno == EINTR) { pr_signals_handle(); continue; } break; }Alternatively, one could block signals before invoking the system call, and unblock signals after the call, to prevent such interruptions. Keep in mind that any signals received while they are masked are silently ignored; they are not queued by the kernel and redelivered to the process once they are unmasked. A process can use the
sigpending(2)
system call to examine
pending signals (i.e. signals that have been raised while blocked),
but this is different from queueing; a process can see which signals
are pending, but not how many of each particular signal have been
raised. The lack of kernel-level support for queueing of blocked signals is,
I suspect, a design decision, possibly because of the possibility of having to
queue an infinite number of signals.
Signal Blocking and Masking
The following functions operate on the signals TERM, CHLD, USR1, INT,
QUIT, ALRM, IO, BUS
and HUP
:
For blocking only SIGALRM
, use these two functions:
The SIGKILL
signal cannot be caught or ignored.
Signal Handlers
The core code implements handlers for the following signals:
SIGABRT
SIGCHLD
SIGUSR1
SIGUSR2
stderr
.
SIGHUP
SIGTERM
SIGXCPU
RLimitCPU
reached; handled by SIGTERM
handler.
SIGINT
SIGTERM
handler in both daemon and session
processes.
SIGILL
SIGTERM
handler in both daemon and session
processes.
SIGFPE
SIGTERM
handler in both daemon and session
processes.
SIGSEGV
SIGTERM
handler in both daemon and session
processes.
SIGURG
SIGSTKFLT
SIGTERM
handler in
both daemon and session processes.
SIGBUS
SIGTERM
handler in
both daemon and session processes.
SIGIO