kill()
). The realtime signals are those whose number
is between the two constants SIGRTMIN and SIGRTMAX, defined in signal.h
.
With the GNU C library SIGRTMIN is actually a function call, as the threading
library reserves some realtime signals for its own use.The signals between SIGRTMIN and SIGRTMAX have no standard purpose and may be used by a program in any way that it sees fit. POSIX mandates at least 8 real time signals be available. On linux signal numbers between 32 and 63 are available, though as previously stated some (presently 3, in the range 32 through 34) are used by the threading library if active.
Lower number signals are given priority over higher number signals. In Linux this is true across the range of all signals, which incidentally gives the regular signals higher priority than all real-time signals (POSIX says that priority of real-time versus ordinary signals is unspecified, and only the realtime signals have a specified priority relative to each other).
On linux there is a system-wide limit to the number of queued signals. This is a potential source of denial-of-service attacks. However, there is a per-user resource limit to control the total number of pending signals that can be allocated to a single user.
struct sigaction
structure. It is:
void (*sa_sigaction)(int, siginfo_t *, void *);
A new flag, SA_SIGINFO
, is used (in the sa_flags
field) to
specify that the sa_sigaction
rather than the sa_handler
field specifies the signal handler.
The siginfo_t structure has at least the following members:
int si_signo; // the signal number int si_errno; // if non-zero, an errno value assosciated with this // signal, as defined inint si_code; // signal code
The si_code
field contains information on the source or cause
of the signal. For non-realtime signals, and signals sent with kill()
or equivalent mechanisms, si_code
will be set to SI_USER
.
(Hmm, except on kernel 2.6.22.6 with glibc 2.6.1 I get SI_TKILL when the
signal was sent via raise(), which is consistent with POSIX which states that
raise may be equivalent to pthread_kill).
Other values for si_code
are not documented here, with one or two
exceptions.
The third argument to the new-style signal handler is a void
pointer referred to as context. However its value is not defined.
sigqueue()
function provides a means to queue a signal, and
provide additional signal data. The function fails immediately if queueing is
not possible.
int sigqueue(pid_t pid, int signo, const union sigval value);
The union sigval
has the following members:
int sival_int; // a simple integer value void *sival_ptr; // a pointer
This union therefore allows either an integer or pointer value to be sent to
the designated process, via the specified signal. As with kill()
,
a signal number of 0 does not result in a signal being delivered but still
performs error checking, so that it can be used to verify if a process with
a given pid actually exists (and determine whether it is owned by the same
user).
Return is 0 if successful, -1 otherwise. The following error conditions (stored
in the errno
variable) apply:
EAGAIN
- the signal buffer is full, so the signal could not be queued
EACCESS
- the sending process does not have permission to send
a signal to the specified process
EINVAL
- the signal number is not valid
ESRCH
- the specified process does not exist
On reception of a real-time signal queued using sigqueue()
, an extended
signal handler will see the si_code
field of the siginfo_t
structure is set to SI_QUEUE, and the value
will be available
from a field called si_value
in the same structure. This is the
only condition under which si_code
can contain SI_QUEUE
.
Note that sending non-realtime signals does not cause multiple signals of the
same number to be queued. If a non-realtime signal is sent using
sigqueue()
, and the same signal is already pending in the
specified process, sigqueue()
returns 0 but does not actually
queue the signal. (Well, with kernel 2.6.22.6 at least, you *can* have two
of the same signal pending: one queued via sigqueue (to the process) plus one
via raise or pthread_kill (to the thread). The thread-specific signal gets
delivered first).
The differences between kill()
and sigqueue()
are:
sigqueue()
can send extra information with the signal
sigqueue()
fails with an error if the signal is a real-time
signal which cannot be queued due to the signal buffer being full (it does
not return an error code if it fails to queue a non-realtime signal however).
kill()
guarentees that the signal will be received, though it may
be merged with an already pending signal. Note that kill()
allows sending
a signal even when the process- or system-wide signal buffer is full,
seeing as a signal without the extra data does not require a slot in the
buffer.
kill()
allows sending a signal to the current process group (pid = 0),
all other processes (pid = -1), a process group id (pid = -pgid), or
a specific process. sigqueue()
only allows sending a signal to a
specific process.
sigsuspend()
function provides no means to retrieve assosciated
extra data sent with a queued signal. The new sigwaitinfo()
function
does exactly that. A third function, sigtimedwait()
, also allows
specifying a timeout value for a signal-wait operation.
#include <signal.h> int sigwaitinfo(const sigset_t *set, const siginfo_t *info); int sigtimedwait(const sigset_t *se, const siginfo_t *info, const struct timespec *timeout);
These functions behave as you would expect if you are familiar with sigsuspend()
.
The specified signals should generally be blocked before the call.
Both functions return the signal number received, or -1 if an error or timout occurs.
For sigwaitinfo()
the only possibly errno
value
is EINTR
, which indicates that a signal not in the specified set
was received.
The sigtimedwait()
function has two additional errno
values, EINVAL
which specifies that the supplied timeout was
invalid and EAGAIN
which specifies that the timeout was reached
without a signal reception occurring.