3. Signal Manager

3.1. Introduction

The signal manager provides the functionality associated with the generation, delivery, and management of process-oriented signals.

The directives provided by the signal manager are:

3.2. Background

3.2.1. Signals

POSIX signals are an asynchronous event mechanism. Each process and thread has a set of signals associated with it. Individual signals may be enabled (e.g. unmasked) or blocked (e.g. ignored) on both a per-thread and process level. Signals which are enabled have a signal handler associated with them. When the signal is generated and conditions are met, then the signal handler is invoked in the proper process or thread context asynchronous relative to the logical thread of execution.

If a signal has been blocked when it is generated, then it is queued and kept pending until the thread or process unblocks the signal or explicitly checks for it. Traditional, non-real-time POSIX signals do not queue. Thus if a process or thread has blocked a particular signal, then multiple occurrences of that signal are recorded as a single occurrence of that signal.

One can check for the set of outstanding signals that have been blocked. Services are provided to check for outstanding process or thread directed signals.

3.2.2. Signal Delivery

Signals which are directed at a thread are delivered to the specified thread.

Signals which are directed at a process are delivered to a thread which is selected based on the following algorithm:

  1. If the action for this signal is currently SIG_IGN, then the signal is simply ignored.
  2. If the currently executing thread has the signal unblocked, then the signal is delivered to it.
  3. If any threads are currently blocked waiting for this signal (sigwait()), then the signal is delivered to the highest priority thread waiting for this signal.
  4. If any other threads are willing to accept delivery of the signal, then the signal is delivered to the highest priority thread of this set. In the event, multiple threads of the same priority are willing to accept this signal, then priority is given first to ready threads, then to threads blocked on calls which may be interrupted, and finally to threads blocked on non-interruptible calls.
  5. In the event the signal still can not be delivered, then it is left pending. The first thread to unblock the signal (sigprocmask() or pthread_sigprocmask()) or to wait for this signal (sigwait()) will be the recipient of the signal.

3.3. Operations

3.3.1. Signal Set Management

Each process and each thread within that process has a set of individual signals and handlers associated with it. Services are provided to construct signal sets for the purposes of building signal sets - type sigset_t - that are used to provide arguments to the services that mask, unmask, and check on pending signals.

3.3.2. Blocking Until Signal Generation

A thread may block until receipt of a signal. The “sigwait” and “pause” families of functions block until the requested signal is received or if using sigtimedwait() until the specified timeout period has elapsed.

3.3.3. Sending a Signal

This is accomplished via one of a number of services that sends a signal to either a process or thread. Signals may be directed at a process by the service kill() or at a thread by the service pthread_kill()

3.4. Directives

This section details the signal manager’s directives. A subsection is dedicated to each of this manager’s directives and describes the calling sequence, related constants, usage, and status codes.

3.4.1. sigaddset - Add a Signal to a Signal Set

CALLING SEQUENCE:

#include <signal.h>
int sigaddset(
    sigset_t *set,
    int       signo
);

STATUS CODES:

The function returns 0 on success, otherwise it returns -1 and sets errno to indicate the error. errno may be set to:

EINVAL Invalid argument passed.

DESCRIPTION:

This function adds the signal signo to the specified signal set.

NOTES:

The set must be initialized using either sigemptyset or sigfillset before using this function.

3.4.2. sigdelset - Delete a Signal from a Signal Set

CALLING SEQUENCE:

#include <signal.h>
int sigdelset(
    sigset_t *set,
    int       signo
);

STATUS CODES:

The function returns 0 on success, otherwise it returns -1 and sets errno to indicate the error. errno may be set to:

EINVAL Invalid argument passed.

DESCRIPTION:

This function deletes the signal specified by signo from the specified signal set.

NOTES:

The set must be initialized using either sigemptyset or sigfillset before using this function.

3.4.3. sigfillset - Fill a Signal Set

CALLING SEQUENCE:

#include <signal.h>
int sigfillset(
    sigset_t *set
);

STATUS CODES:

The function returns 0 on success, otherwise it returns -1 and sets errno to indicate the error. errno may be set to:

EINVAL Invalid argument passed.

DESCRIPTION:

This function fills the specified signal set such that all signals are set.

3.4.4. sigismember - Is Signal a Member of a Signal Set

CALLING SEQUENCE:

#include <signal.h>
int sigismember(
    const sigset_t *set,
    int             signo
);

STATUS CODES:

The function returns either 1 or 0 if completed successfully, otherwise it returns -1 and sets errno to indicate the error. errno may be set to:

EINVAL Invalid argument passed.

DESCRIPTION:

This function returns returns 1 if signo is a member of set and 0 otherwise.

NOTES:

The set must be initialized using either sigemptyset or sigfillset before using this function.

3.4.5. sigemptyset - Empty a Signal Set

CALLING SEQUENCE:

#include <signal.h>
int sigemptyset(
    sigset_t *set
);

STATUS CODES:

The function returns 0 on success, otherwise it returns -1 and sets errno to indicate the error. errno may be set to:

EINVAL Invalid argument passed.

DESCRIPTION:

This function initializes an empty signal set pointed to by set.

3.4.6. sigaction - Examine and Change Signal Action

CALLING SEQUENCE:

#include <signal.h>
int sigaction(
    int                     sig,
    const struct sigaction *act,
    struct sigaction       *oact
);

STATUS CODES:

The function returns 0 on success, otherwise it returns -1 and sets errno to indicate the error. errno may be set to:

EINVAL Invalid argument passed.
ENOTSUP Realtime Signals Extension option not supported.

DESCRIPTION:

If the argument act is not a null pointer, it points to a structure specifying the action to be associated with the specified signal. If the argument oact is not a null pointer, the action previously associated with the signal is stored in the location pointed to by the argument oact. If the argument act is a null pointer, signal handling is unchanged; thus, the call can be used to enquire about the current handling of a given signal.

The structure sigaction has the following members:

void(*)(int) sa_handler Pointer to a signal-catching function or one of the macros SIG_IGN or SIG_DFL.
sigset_t sa_mask Additional set of signals to be blocked during execution of signal-catching function.
int sa_flags Special flags to affect behavior of signal.
void(*)(int, siginfo_t*, void*) sa_sigaction Alternative pointer to a signal-catching function.

sa_handler and sa_sigaction should never be used at the same time as their storage may overlap.

If the SA_SIGINFO flag (see below) is set in sa_flags, the sa_sigaction field specifies a signal-catching function, otherwise``sa_handler`` specifies the action to be associated with the signal, which may be a signal-catching function or one of the macros SIG_IGN or SIG_DFN.

The following flags can be set in the sa_flags field:

SA_SIGINFO If not set, the signal-catching function should be declared as void func(int signo) and the address of the function should be set in``sa_handler``. If set, the signal-catching function should be declared as void func(int signo, siginfo_t* info, void* context) and the address of the function should be set in sa_sigaction.

The prototype of the siginfo_t structure is the following:

typedef struct
{
    int si_signo;        /* Signal number */
    int si_code;         /* Cause of the signal */
    pid_t si_pid;        /* Sending process ID */
    uid_t si_uid;        /* Real user ID of sending process */
    void* si_addr;       /* Address of faulting instruction */
    int si_status;       /* Exit value or signal */
    union sigval
    {
        int sival_int;   /* Integer signal value */
        void* sival_ptr; /* Pointer signal value */
    } si_value;          /* Signal value */
}

NOTES:

The signal number cannot be SIGKILL.

3.4.7. pthread_kill - Send a Signal to a Thread

CALLING SEQUENCE:

#include <signal.h>
int pthread_kill(
    pthread_t thread,
    int       sig
);

STATUS CODES:

The function returns 0 on success, otherwise it returns -1 and sets errno to indicate the error. errno may be set to:

ESRCH The thread indicated by the parameter thread is invalid.
EINVAL Invalid argument passed.

DESCRIPTION:

This functions sends the specified signal sig to a thread referenced to by thread.

If the signal code is 0, arguments are validated and no signal is sent.

3.4.8. sigprocmask - Examine and Change Process Blocked Signals

CALLING SEQUENCE:

#include <signal.h>
int sigprocmask(
    int             how,
    const sigset_t *set,
    sigset_t       *oset
);

STATUS CODES:

The function returns 0 on success, otherwise it returns -1 and sets errno to indicate the error. errno may be set to:

EINVAL Invalid argument passed.

DESCRIPTION:

This function is used to alter the set of currently blocked signals on a process wide basis. A blocked signal will not be received by the process. The behavior of this function is dependent on the value of how which may be one of the following:

SIG_BLOCK The set of blocked signals is set to the union of set and those signals currently blocked.
SIG_UNBLOCK The signals specific in set are removed from the currently blocked set.
SIG_SETMASK The set of currently blocked signals is set to set.

If oset is not NULL, then the set of blocked signals prior to this call is returned in oset. If set is NULL, no change is done, allowing to examine the set of currently blocked signals.

NOTES:

It is not an error to unblock a signal which is not blocked.

In the current implementation of RTEMS POSIX API sigprocmask() is technically mapped to pthread_sigmask().

3.4.9. pthread_sigmask - Examine and Change Thread Blocked Signals

CALLING SEQUENCE:

#include <signal.h>
int pthread_sigmask(
int             how,
const sigset_t *set,
sigset_t       *oset
);

STATUS CODES:

The function returns 0 on success, otherwise it returns -1 and sets errno to indicate the error. errno may be set to:

EINVAL
Invalid argument passed.

DESCRIPTION:

This function is used to alter the set of currently blocked signals for the calling thread. A blocked signal will not be received by the process. The behavior of this function is dependent on the value of how which may be one of the following:

SIG_BLOCK The set of blocked signals is set to the union of set and those signals currently blocked.
SIG_UNBLOCK The signals specific in set are removed from the currently blocked set.
SIG_SETMASK The set of currently blocked signals is set to set.

If oset is not NULL, then the set of blocked signals prior to this call is returned in oset. If set is NULL, no change is done, allowing to examine the set of currently blocked signals.

NOTES:

It is not an error to unblock a signal which is not blocked.

3.4.10. kill - Send a Signal to a Process

CALLING SEQUENCE:

#include <sys/types.h>
#include <signal.h>
int kill(
    pid_t pid,
    int   sig
);

STATUS CODES:

The function returns 0 on success, otherwise it returns -1 and sets errno to indicate the error. errno may be set to:

EINVAL Invalid argument passed.
EPERM Process does not have permission to send the signal to any receiving process.
ESRCH The process indicated by the parameter pid is invalid.

DESCRIPTION:

This function sends the signal sig to the process pid.

NOTES:

Since RTEMS is a single-process system, a signal can only be sent to the calling process (i.e. the current node).

3.4.11. sigpending - Examine Pending Signals

CALLING SEQUENCE:

#include <signal.h>
    int sigpending(
    const sigset_t *set
);

STATUS CODES:

The function returns 0 on success, otherwise it returns -1 and sets errno to indicate the error. errno may be set to:

EFAULT Invalid address for set.

DESCRIPTION:

This function allows the caller to examine the set of currently pending signals. A pending signal is one which has been raised but is currently blocked. The set of pending signals is returned in set.

3.4.12. sigsuspend - Wait for a Signal

CALLING SEQUENCE:

#include <signal.h>
   int sigsuspend(
   const sigset_t *sigmask
);

STATUS CODES:

The function returns 0 on success, otherwise it returns -1 and sets errno to indicate the error. errno may be set to:

EINTR Signal interrupted this function.

DESCRIPTION:

This function temporarily replaces the signal mask for the process with that specified by sigmask and blocks the calling thread until a signal is raised.

3.4.13. pause - Suspend Process Execution

CALLING SEQUENCE:

#include <signal.h>
int pause( void );

STATUS CODES:

The function returns 0 on success, otherwise it returns -1 and sets errno to indicate the error. errno may be set to:

EINTR Signal interrupted this function.

DESCRIPTION:

This function causes the calling thread to be blocked until an unblocked signal is received.

3.4.14. sigwait - Synchronously Accept a Signal

CALLING SEQUENCE:

#include <signal.h>
int sigwait(
    const sigset_t *set,
    int            *sig
);

STATUS CODES:

The function returns 0 on success, otherwise it returns -1 and sets errno to indicate the error. errno may be set to:

EINVAL Invalid argument passed.
EINTR Signal interrupted this function.

DESCRIPTION:

This function selects a pending signal based on the set specified in set, atomically clears it from the set of pending signals, and returns the signal number for that signal in sig.

3.4.15. sigwaitinfo - Synchronously Accept a Signal

CALLING SEQUENCE:

#include <signal.h>
int sigwaitinfo(
    const sigset_t *set,
    siginfo_t      *info
);

STATUS CODES:

The function returns 0 on success, otherwise it returns -1 and sets errno to indicate the error. errno may be set to:

EINTR
Signal interrupted this function.

DESCRIPTION:

This function selects a pending signal based on the set specified in set, atomically clears it from the set of pending signals, and returns information about that signal in info.

The prototype of the siginfo_t structure is the following:

typedef struct
{
    int si_signo;        /* Signal number */
    int si_code;         /* Cause of the signal */
    pid_t si_pid;        /* Sending process ID */
    uid_t si_uid;        /* Real user ID of sending process */
    void* si_addr;       /* Address of faulting instruction */
    int si_status;       /* Exit value or signal */
    union sigval
    {
        int sival_int;   /* Integer signal value */
        void* sival_ptr; /* Pointer signal value */
    } si_value;          /* Signal value */
}

3.4.16. sigtimedwait - Synchronously Accept a Signal with Timeout

CALLING SEQUENCE:

#include <signal.h>
int sigtimedwait(
    const sigset_t        *set,
    siginfo_t             *info,
    const struct timespec *timeout
);

STATUS CODES:

The function returns 0 on success, otherwise it returns -1 and sets errno to indicate the error. errno may be set to:

EAGAIN Timed out while waiting for the specified signal set.
EINVAL Nanoseconds field of the timeout argument is invalid.
EINTR Signal interrupted this function.

DESCRIPTION:

This function selects a pending signal based on the set specified in set, atomically clears it from the set of pending signals, and returns information about that signal in info. The calling thread will block up to timeout waiting for the signal to arrive.

The timespec structure is defined as follows:

struct timespec
{
    time_t tv_sec; /* Seconds */
    long tv_nsec;  /* Nanoseconds */
}

NOTES:

If timeout is NULL, then the calling thread will wait forever for the specified signal set.

3.4.17. sigqueue - Queue a Signal to a Process

CALLING SEQUENCE:

#include <signal.h>
int sigqueue(
    pid_t              pid,
    int                signo,
    const union sigval value
);

STATUS CODES:

The function returns 0 on success, otherwise it returns -1 and sets errno to indicate the error. errno may be set to:

EAGAIN No resources available to queue the signal. The process has already queued SIGQUEUE_MAX signals that are still pending at the receiver or the systemwide resource limit has been exceeded.
EINVAL The value of the signo argument is an invalid or unsupported signal number.
EPERM The process does not have the appropriate privilege to send the signal to the receiving process.
ESRCH The process pid does not exist.

DESCRIPTION:

This function sends the signal specified by signo to the process pid

The sigval union is specified as:

union sigval
{
    int sival_int; /* Integer signal value */
    void* sival_ptr; /* Pointer signal value */
}

NOTES:

Since RTEMS is a single-process system, a signal can only be sent to the calling process (i.e. the current node).

3.4.18. alarm - Schedule Alarm

CALLING SEQUENCE:

#include <unistd.h>
unsigned int alarm(
    unsigned int seconds
);

STATUS CODES:

This call always succeeds.

If there was a previous alarm() request with time remaining, then this routine returns the number of seconds until that outstanding alarm would have fired. If no previous alarm() request was outstanding, then zero is returned.

DESCRIPTION:

The alarm() service causes the SIGALRM signal to be generated after the number of seconds specified by seconds has elapsed.

NOTES:

Alarm requests do not queue. If alarm is called while a previous request is outstanding, the call will result in rescheduling the time at which the SIGALRM signal will be generated.

If the notification signal, SIGALRM, is not caught or ignored, the calling process is terminated.

3.4.19. ualarm - Schedule Alarm in Microseconds

CALLING SEQUENCE:

#include <unistd.h>
useconds_t ualarm(
    useconds_t useconds,
    useconds_t interval
);

STATUS CODES:

This call always succeeds.

If there was a previous ualarm() request with time remaining, then this routine returns the number of seconds until that outstanding alarm would have fired. If no previous alarm() request was outstanding, then zero is returned.

DESCRIPTION:

The ualarm() service causes the SIGALRM signal to be generated after the number of microseconds specified by useconds has elapsed.

When interval is non-zero, repeated timeout notification occurs with a period in microseconds specified by interval.

NOTES:

Alarm requests do not queue. If alarm is called while a previous request is outstanding, the call will result in rescheduling the time at which the SIGALRM signal will be generated.

If the notification signal, SIGALRM, is not caught or ignored, the calling process is terminated.