Send a signal to a process group, process, or thread
#include <sys/neutrino.h> int SignalKill( uint32_t nd, pid_t pid, int tid, int signo, int code, int value ); int SignalKill_r( uint32_t nd, pid_t pid, int tid, int signo, int code, int value );
- The node descriptor of the node on which to look for pid and tid. To search the local node, set nd to ND_LOCAL_NODE or 0.
- 0, or the ID of the process to send the signal to; see below.
- 0, or the ID of the thread to send the signal to; see below.
- The signal that you want to send. There are a total of 64 signals available. Of these, at least 8 are POSIX realtime signals that range from SIGRTMIN to SIGRTMAX. For a complete list of signals, see POSIX signals in the documentation for SignalAction(). Valid user signals range from 1 to (NSIG - 1).
- code, value
- The code and value associated with the signal; see SignalAction() .
Use the -l c option to qcc to link against this library. This library is usually included automatically.
The SignalKill() and SignalKill_r() kernel calls send the signal signo with a code specified by code and a value specified by value to a process group, process, or thread.
These functions are identical except in the way they indicate errors. See the Returns section for details.
If signo is zero, no signal is sent, but the validity of pid and tid are checked. You can use this as a test for existence.
The pid and tid determine the target of the signal, as follows:
|= 0||—||Hit the process group of the caller|
|< 0||—||Hit a process group identified by -pid|
|> 0||= 0||Hit a single process identified by pid|
|> 0||> 0||Hit a single thread in process pid identified by tid|
If the target is a thread, the signal is always delivered to exactly that thread. If the thread has the signal blocked — see SignalProcmask() — the signal remains pending on the thread.
If the target is a process, the signal is delivered to a thread that has the signal unblocked; see SignalProcmask(), SignalSuspend() , and SignalWaitinfo() . If multiple threads have the signal unblocked, only one thread is given the signal. Which thread receives the signal isn't deterministic. To make it deterministic, you can:
- Have all threads except one block all signals; that thread
handles all signals.
- Target the signals to specific threads.
If all threads have the signal blocked, it's made pending on the process. The first thread to unblock the signal receives the pending signal. If a signal is pending on a thread, it's never retargetted to the process or another thread, regardless of changes to the signal-blocked mask.
If the target is a process group, the signal is delivered as above to each process in the group.
A multithreaded application typically has one thread responsible for catching most or all signals. Threads that don't wish to be directly involved with signals block all signals in their mask.
The signal-blocked mask is maintained on a per-thread basis. The signal-ignore mask and signal handlers are maintained at the process level and are shared by all threads.
If multiple signals are delivered before the target can run and process the signals, the system queues them in priority order if the SA_SIGINFO bit was set for signo. Lower numbered signals have greater priority. If the SA_SIGINFO bit isn't set for signo, then at most one signal is queued at any time. Additional signals with the same signo replace existing ones. This is the default behavior for POSIX signal handlers installed using the old signal() function. The newer sigaction() function lets you control queuing or not on a per-signal basis. Signals with a code of SI_TIMER are never queued.
The code and value are always saved with the signal. This allows you to deliver data with the signal whether or not SA_SIGINFO has been set on the signo. If SA_SIGINFO is set, you can use signals to deliver small amounts of data without loss. If you wish to pass significant data, you may wish to consider using MsgSendPulse() and MsgSendv() , which deliver data with much greater efficiency.
When a thread receives a signal by a signal handler or SignalWaitinfo() call, it can retrieve the signo, code and value from a siginfo_t structure, which contains at least the following members:
- int si_signo
- The signal number.
- int si_code
- The signal code.
- union sigval si_value
- The signal value.
The value of si_code is limited to an 8-bit signed value as follows:
|-128 <= si_code <= 0||User values|
|0 < signo <= 127||System values generated by the kernel|
Some of the common user values defined by POSIX are:
- 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) messages queues generated the signal.
A successful return from this function means the signal has been delivered. What the process(es) or thread does with the signal isn't considered.
If a thread delivers signals that the receiving process has marked as queued faster than the receiver can consume them, the kernel may fail the call if it runs out of signal queue entries. If the signo, code, and value don't change, the kernel performs signal compression by saving an 8-bit count with each queued signal.
None. In the network case, lower priority threads may run.
The only difference between these functions is the way they indicate errors:
- If an error occurs, -1 is returned and sets errno . Any other value returned indicates success.
- EOK is returned on success. This function does NOT set errno. If an error occurs, any value in the Errors section may be returned.
- The kernel had insufficient resources to enqueue the signal.
- The value of signo is less than 0 or greater than (_NSIG -1).
- The calling process doesn't have the required permission; see procmgr_ability() .
- The process or process group indicated by pid or thread indicated by tid doesn't exist.