Signals are software interrupts that can be sent to a running process or thread to indicate exceptional situations. The action taken when an event is received depends on the current settings for the signal and may be set to either:
When a signal is received, unless it is ignored or blocked the action for the signal will preempt any code that is currently executing. Also, signals are asynchronous and may arrive at any time. See http://man7.org/linux/man-pages/man7/signal.7.html for more details.
The asynchronous and preemptive nature of signals can be difficult to deal with and is often a source of race conditions. Moreover asynchronous and preemptive signal handling is often unnecessary so code often looks something like this:
In this code sample, the signal handler is only used to set a flag, while the main loop handles the actual signal processing. But handling signals this way requires the main loop to run continuously. This code is also prone to errors. For example, if the clearing of the flags was done after processing of the signal, any signals received during processing of the signals will be lost.
The Legato signals API provides a simpler alternative, called signal events. Signal events can be used to receive and handle signals synchronously without the need for a sit-and-wait loop or even a block-and-wait call.
To use signal events, the desired signals must first be blocked using le_sig_Block() (see Blocking signals). Then set a signal event handler for the desired signal using le_sig_SetEventHandler()
. Once a signal to the thread is received, the signal event handler is called by the thread's Legato event loop (see Event Loop API for more details). The handler is called synchronously in the context of the thread that set the handler. Be aware that if the thread's event loop is not called or is blocked by some other code, the signal event handler will also be blocked.
Here is an example using signal events to handle the SIGCHLD signals:
Signal events work well when dealing with signals synchronously, but when signals must be dealt with in an asynchronously, traditional signal handlers are still preferred. In fact, signal event handlers are not allowed for certain signals like program error signals (ie. SIGFPE, etc.) because they indicate a serious error in the program and all code outside of signal handlers are considered unreliable. This means that asynchronous signal handlers are the only option when dealing with program error signals.
Signal event handlers can be used in conjunction with asynchronous signal handlers but only if they do not deal with the same signals. In fact all signals that use signal events must be blocked for every thread in the process. The Legato framework takes care of this for you when you set the signals you want to use in the Legato build system.
If your code explicitly unblocks a signal where you currently have signal event handlers, the signal event handlers will no longer be called until the signal is blocked again.
In a multi-threaded system, signals can be sent to either the process or a specific thread. Signals directed at a specific thread will be received by that thread; signals directed at the process are received by one of the threads in the process that has a handler for the signal.
It is unspecified which thread will actually receive the signal so it's recommended to only have one signal event handler per signal.
A limitation of signals in general (not just with signal events) is called signal merging. Signals that are received but not yet handled are said to be pending. If another signal of the same type is received while the first signal is pending, then the two signals will merge into a single signal and there will be only one handler function call. Consequently, it is not possible to reliably know how many signals arrived.
Signals that are to be used with a signal event handlers must be blocked for the entire process. To ensure this use le_sig_Block() to block signals in the process' first thread. All other threads will inherit the signal mask from the first thread.
The example below shows how to use a signal event in a separate thread.
Copyright (C) Sierra Wireless Inc. Use of this work is subject to license.