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
SIGUSR2stderr.
SIGHUP
SIGTERM
SIGXCPURLimitCPU reached; handled by SIGTERM handler.
SIGINTSIGTERM handler in both daemon and session
processes.
SIGILLSIGTERM handler in both daemon and session
processes.
SIGFPESIGTERM handler in both daemon and session
processes.
SIGSEGVSIGTERM handler in both daemon and session
processes.
SIGURG
SIGSTKFLTSIGTERM handler in
both daemon and session processes.
SIGBUSSIGTERM handler in
both daemon and session processes.
SIGIO