SignalAction(), SignalAction_r()

Examine and/or specify actions for signals

Synopsis:

#include <sys/neutrino.h>

int SignalAction( pid_t pid,
                  void ( * sigstub)(),
                  int signo,
                  const struct sigaction * act,
                  struct sigaction * oact );

int SignalAction_r( pid_t pid,
                    void * (sigstub)(),
                    int signo,
                    const struct sigaction * act,
                    struct sigaction * oact );

Arguments:

pid
A process ID, or 0 for the current process.
sigstub
The address of a signal stub handler. This is a small piece of code in the user's space that interfaces the user's signal handler to the kernel. The library provides a standard one, __signalstub(). This argument can be NULL if act is also NULL.
signo
The signal whose action you want to set or get; see "POSIX signals," below.
act
NULL, or a pointer to a sigaction structure that specifies the new action for the signal. For more information, see "Signal actions," below.
oact
NULL, or a pointer to a sigaction structure where the function can store the old action.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

The SignalAction() and SignalAction_r() kernel calls let the calling process examine or specify (or both) the action to be associated with a specific signal in the process pid. If pid is zero, the calling process is used. The argument signo specifies the signal.

Note:
  • You should call the POSIX sigaction() function or the ANSI signal() function instead of using these kernel calls directly.
  • In order to attach signal handlers to a process with a different real or effective user ID, your process must have the PROCMGR_AID_SIGNAL ability enabled. For more information, see procmgr_ability().
  • If the signal terminates a process, the cleanup of the terminated process occurs at the priority of the thread that set the signal.

These functions are identical except in the way they indicate errors. See the Returns section for details.

POSIX signals

The signals are defined in <signal.h>, and so are these global variables:

char * const sys_siglist[]
An array of signal names.
int sys_nsig
The number of entries in the sys_siglist array.

The entire range of signals goes from _SIGMIN (1) to _SIGMAX (64):

Signal range Description
1–57 57 POSIX signals (including traditional UNIX signals)
41–56 16 POSIX realtime signals (SIGRTMIN to SIGRTMAX)
57–64 Eight special-purpose QNX Neutrino signals, some of which are named (e.g., SIGSELECT). They're always masked, and attempts to unmask them are ignored.

The POSIX and UNIX signals include:

Signal Description Default action
SIGABRT Used by abort() Write a dump file and kill the process
SIGALRM Realtime alarm clock Kill the process
SIGBUS Bus error Write a dump file and kill the process
SIGCHLD or SIGCLD Death of child Ignore the signal, but still let the process's children become zombies
SIGCONTa Continue the process Make the process continue if it's stopped; otherwise ignore the signal
SIGDEADLKb Mutex deadlock; see SyncMutexEvent() Write a dump file and kill the process
SIGEMTb EMT instruction (emulation trap) Write a dump file and kill the process
SIGFPE Floating point exception Write a dump file and kill the process
SIGHUP Hangup Kill the process
SIGILLc Illegal instruction (not reset when caught) Write a dump file and kill the process
SIGINT Interrupt Kill the process
SIGIO Asynchronous I/O Ignore the signal
SIGIOT IOT instruction Kill the process
SIGKILLa Kill Kill the process
SIGPIPE Write on pipe with no reader Kill the process
SIGPOLL System V name for SIGIO Ignore the signal
SIGPROF Profiling timer expired Kill the process
SIGPWR Power-fail restart Kill the process
SIGQUIT Quit Write a dump file and kill the process
SIGSEGV Segmentation violation Write a dump file and kill the process
SIGSTOPa Stop executing Stop the process
SIGSYS Bad argument to system call Write a dump file and kill the process
SIGTERM Software termination signal from kill Kill the process
SIGTRAP Trace trap (not reset when caught) Write a dump file and kill the process
SIGTSTP Stop signal from tty Stop the process
SIGTTIN Attempted background tty read Stop the process
SIGTTOU Attempted background tty write Stop the process
SIGURG Urgent condition on I/O channel Ignore the signal
SIGUSR1 User-defined signal 1 Kill the process
SIGUSR2 User-defined signal 2 Kill the process
SIGVTARLM Virtual timer expired Kill the process
SIGWINCH Window change Ignore the signal
SIGXCPU CPU time limit exceeded Write a dump file and kill the process

a You can't ignore or catch SIGCONT, SIGKILL, or SIGSTOP.

b SIGDEADLK and SIGEMT refer to the same signal.

c One possible cause for a SIGILL signal is trying to perform an operation that requires I/O privileges. A thread can request these privileges by making sure it has the PROCMGR_AID_IO ability enabled (see procmgr_ability()) and then calling ThreadCtl(), specifying the _NTO_TCTL_IO flag:

ThreadCtl( _NTO_TCTL_IO, 0 );

Signal actions

If act isn't NULL, then the specified signal is modified. If oact isn't NULL, the previous action is stored in the structure it points to. You can use various combinations of act and oact to query or set (or both) the action for a signal.

The structure sigaction contains the following members:

void (*sa_handler)();
The address of a signal handler or action for nonqueued signals.
void (*sa_sigaction) (int signo, siginfo_t *info, void *other);
The address of a signal handler or action for queued signals.
sigset_t sa_mask
An additional set of signals to be masked (blocked) during execution of the signal-catching function.
int sa_flags
Special flags that affect the behavior of the signal:
  • SA_NOCLDSTOP — don't generate a SIGCHLD on the parent for children who stop via SIGSTOP. This flag is used only when the signal is SIGCHLD.
  • SA_SIGINFO — queue this signal. The default is not to queue a signal delivered to a process. If a signal isn't queued, and the same signal is set multiple times on a process or thread before it runs, only the last signal is delivered. If you set the SA_SIGINFO flag, the signals are queued, and they're all delivered.

The sa_handler and sa_sigaction members of act are implemented as a union, and share common storage. They differ only in their prototype, with sa_handler being used for POSIX 1003.1a signals, and sa_sigaction being used for POSIX 1003.1b queued realtime signals. The values stored using either name can be one of:

function
The address of a signal-catching function. See below for details.
SIG_DFL
Use the default action for the signal:
  • SIGIO, SIGURG, and SIGWINCH: ignore the signal.
  • SIGCHLD: ignore the signal, but still let the process's children become zombies.
  • SIGSTOP, SIGTSTP, SIGTTIN, and SIGTTOU: stop the process.
  • SIGCONT: make the program continue.
  • SIGABRT, SIGBUS, SIGEMT (or SIGDEADLK), SIGFPE, SIGILL, SIGQUIT, SIGSEGV, SIGSYS, SIGTRAP, and SIGXCPU: write a dump file and kill the process.
  • all other signals: kill the process.
SIG_IGN
Ignore the signal. Setting SIG_IGN for a signal that's pending discards all pending signals, whether it's blocked or not. New signals are discarded. If you set the action for SIGCHLD to SIG_IGN, your process's children won't enter the zombie state, and the process won't be able to use wait() or waitpid() to wait on their deaths.

The function member of sa_handler or sa_sigaction is always invoked with the following arguments:

void handler(int signo, siginfo_t* info, void* other)

If you have an old-style signal handler of the form:

void handler(int signo)

the microkernel passes the extra arguments, but the function simply ignores them.

While in the handler, signo is masked, preventing nested signals of the same type. In addition, any signals set in the sa_mask member of act are also ORed into the mask. When the handler returns through a normal return, the previous mask is restored, and any pending and now unmasked signals are acted on. You return to the point in the program where it was interrupted. If the thread was blocked in the kernel when the interruption occurred, the kernel call returns with an EINTR (see ChannelCreate() and SyncMutexLock() for exceptions to this).

Note: It isn't safe to use floating-point operations in signal handlers.

When you specify a handler, you must provide the address of a signal stub handler for sigstub. This is a small piece of code in the user's space that interfaces the user's signal handler to the kernel. The library provides a standard one, __signalstub().

The siginfo_t structure of the function in sa_handler or sa_sigaction contains at least the following members:

int si_signo
The signal number, which should match the signo argument to the handler.
int si_code
A signal code, provided by the generator of the signal:
  • SI_USER — the kill() function generated the signal.
  • SI_QUEUE — the sigqueue() function generated the signal.
  • SI_TIMER — a timer generated the signal.
  • SI_ASYNCIO — asynchronous I/O generated the signal.
  • SI_MESGQ — POSIX (not QNX Neutrino) messages queues generated the signal.
union sigval si_value
A value associated with the signal, provided by the generator of the signal.

Signal handlers and actions are defined for the process and affect all threads in the process. For example, if one thread ignores a signal, then all threads ignore the signal.

You can target a signal at a thread, process or process group (see SignalKill()). When targeted at a process, at most one thread receives the signal. This thread must have the signal unblocked (see SignalProcmask()) to be a candidate for receiving it. All synchronously generated signals (e.g. SIGSEGV) are always delivered to the thread that caused them.

In a multithreaded process, if a signal terminates a thread, by default all threads and thus the process are terminated. You can override this standard POSIX behavior when you create the thread; see ThreadCreate().

CAUTION:
If you use longjmp() to return from a signal handler, the signal remains masked. You can use siglongjmp() to restore the mask to the state saved by a previous call to sigsetjmp().

Blocking states

These calls don't block.

Returns:

The only difference between these functions is the way they indicate errors:

SignalAction()
If an error occurs, -1 is returned and errno is set. Any other value returned indicates success.
SignalAction_r()
EOK is returned on success. This function does NOT set errno. If an error occurs, any value in the Errors section may be returned.

Errors:

EAGAIN
The system was unable to allocate a signal handler. This indicated critically low memory.
EFAULT
A fault occurred when the kernel tried to access the buffers provided.
EINVAL
The value of signo is less than 1 or greater than _SIGMAX, or you tried to set SIGKILL or SIGSTOP to something other than SIG_DFL.
EPERM
The calling process doesn't have the required permission; see procmgr_ability().
ESRCH
The process indicated by pid doesn't exist.

Classification:

QNX Neutrino

Safety:  
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes