le_signals.h

Go to the documentation of this file.
1 /**
2  * @page c_signals Signals API
3  *
4  * @ref le_signals.h "API Reference"
5  *
6  * <HR>
7  *
8  * Signals are software interrupts that can be sent to a running process or thread to
9  * indicate exceptional situations. The action taken when an event is received depends on the
10  * current settings for the signal and may be set to either:
11  *
12  * - Operating systems default action.
13  * - Ignore the signal.
14  * - A custom handler.
15  *
16  * When a signal is received, unless it is ignored or blocked the action for the signal will preempt
17  * any code that is currently executing. Also, signals are asynchronous and may arrive at any time.
18  * See http://man7.org/linux/man-pages/man7/signal.7.html for more details.
19  *
20  * The asynchronous and preemptive nature of signals can be difficult to deal with and is often a
21  * source of race conditions. Moreover asynchronous and preemptive signal handling is often
22  * unnecessary so code often looks something like this:
23  *
24  * @code
25  * // A global volatile atomic flag.
26  * static volatile int GotSignal;
27  *
28  * void sigHandler(int sigNum)
29  * {
30  * // Must only use asynch-signal-safe functions in this handler, see signals(7) man page for
31  * // more details.
32  *
33  * // Set the flag.
34  * GotSignal = 1;
35  * }
36  *
37  * int main (void)
38  * {
39  * while(1)
40  * {
41  * // Do something.
42  * ...
43  *
44  * if (GotSignal = 1)
45  * {
46  * // Clear the flag.
47  * GotSignal = 0;
48  *
49  * // Process the signal.
50  * ...
51  * }
52  * }
53  * }
54  * @endcode
55  *
56  * In this code sample, the signal handler is only used to set a flag, while the main loop handles
57  * the actual signal processing. But handling signals this way requires the main loop to run
58  * continuously. This code is also prone to errors. For example, if the clearing of the flags was
59  * done after processing of the signal, any signals received during processing of the signals will
60  * be lost.
61  *
62  * @section c_signals_eventHandlers Signal Event Handlers
63  *
64  * The Legato signals API provides a simpler alternative, called signal events. Signal events can
65  * be used to receive and handle signals synchronously without the need for a sit-and-wait loop or
66  * even a block-and-wait call.
67  *
68  * To use signal events, the desired signals must first be blocked using le_sig_Block() (see
69  * @ref c_signals_blocking). Then set a signal event handler for the desired signal using
70  * @c le_sig_SetEventHandler(). Once a signal to the thread is received, the signal event handler
71  * is called by the thread's Legato event loop (see @ref c_eventLoop for more details). The handler
72  * is called synchronously in the context of the thread that set the handler. Be aware that if the
73  * thread's event loop is not called or is blocked by some other code, the signal event handler will
74  * also be blocked.
75  *
76  * Here is an example using signal events to handle the SIGCHLD signals:
77  *
78  * @code
79  * // SIGCHILD event handler that will be called as a synchronous event.
80  * static void SigChildEventHandler(int sigNum)
81  * {
82  * // Handle SIGCHLD event.
83  * ...
84  *
85  * // There is no need to limit ourselves to async-signal-safe functions because we are now in
86  * // a synchronous event handler.
87  * }
88  *
89  *
90  * COMPONENT_INIT
91  * {
92  * // Block Signals that we are going to set event handlers for.
93  * le_sig_Block(SIGCHLD);
94  *
95  * // Setup the signal event handler.
96  * le_sig_SetEventHandler(SIGCHILD, SigChildEventHandler);
97  * }
98  * @endcode
99  *
100  *
101  * @section c_signals_mixedHandlers Mixing Asynchronous Signal Handlers with Synchronous Signal Event Handlers
102  *
103  * Signal events work well when dealing with signals synchronously, but when signals must be dealt
104  * with in an asynchronously, traditional signal handlers are still preferred. In fact, signal
105  * event handlers are not allowed for certain signals like program error signals (ie. SIGFPE,
106  * etc.) because they indicate a serious error in the program and all code outside of signal
107  * handlers are considered unreliable. This means that asynchronous signal handlers are the only
108  * option when dealing with program error signals.
109  *
110  * Signal event handlers can be used in conjunction with asynchronous signal handlers but
111  * only if they do not deal with the same signals. In fact all signals that use signal events must
112  * be blocked for every thread in the process. The Legato framework takes care of this for you when
113  * you set the signals you want to use in the Legato build system.
114  *
115  * If your code explicitly unblocks a signal where you currently have signal event handlers, the
116  * signal event handlers will no longer be called until the signal is blocked again.
117  *
118  * @section c_signals_multiThread Multi-Threading Support
119  *
120  * In a multi-threaded system, signals can be sent to either the process or a specific thread.
121  * Signals directed at a specific thread will be received by that thread; signals directed at
122  * the process are received by one of the threads in the process that has a handler for the signal.
123  *
124  * It is unspecified which thread will actually receive the signal so it's recommended
125  * to only have one signal event handler per signal.
126  *
127  * @section c_signals_limitations Limitations and Warnings
128  *
129  * A limitation of signals in general (not just with signal events) is called signal merging.
130  * Signals that are received but not yet handled are said to be pending. If another signal of the
131  * same type is received while the first signal is pending, then the two signals will merge into a
132  * single signal and there will be only one handler function call. Consequently, it is not possible
133  * to reliably know how many signals arrived.
134  *
135  *
136  * @warning Signals are difficult to deal with in general because of their asynchronous nature and
137  * although, Legato has simplified the situation with signal events certain limitations still exist.
138  * If possible, avoid using them.
139  *
140  * @section c_signals_blocking Blocking signals
141  *
142  * Signals that are to be used with a signal event handlers must be blocked for the entire process.
143  * To ensure this use le_sig_Block() to block signals in the process' first thread. All other
144  * threads will inherit the signal mask from the first thread.
145  *
146  * The example below shows how to use a signal event in a separate thread.
147  *
148  * @code
149  * // SIGCHILD event handler that will be called as a synchronous event in the context of the
150  * // workThread.
151  * static void SigChildEventHandler(int sigNum)
152  * {
153  * // Handle SIGCHILD event.
154  * ...
155  *
156  * // There is no need to limit ourselves to async-signal-safe functions because we are now in
157  * // a synchronous event handler.
158  * }
159  *
160  *
161  * // Work thread's main function.
162  * static void* WorkThreadMain(void* context)
163  * {
164  * // Setup the signal event handler.
165  * le_sig_SetEventHandler(SIGCHILD, SigChildEventHandler);
166  *
167  * // Start this thread's event loop.
168  * le_event_RunLoop();
169  *
170  * return NULL;
171  * }
172  *
173  *
174  * // Main thread code.
175  * COMPONENT_INIT
176  * {
177  * // Block Signals that we are going to set event handlers for in the main thread so that all
178  * // subsequent threads will inherit the same signal mask.
179  * le_sig_Block(SIGCHLD);
180  *
181  * // Create and start a work thread that will actually handle the signal.
182  * le_thread_Ref_t workThread = le_thread_Create("workThread", WorkThread, NULL);
183  *
184  * le_thread_Start(workThread);
185  * }
186  * @endcode
187  *
188  * <HR>
189  *
190  * Copyright (C) Sierra Wireless Inc.
191  */
192 
193 //--------------------------------------------------------------------------------------------------
194 /** @file le_signals.h
195  *
196  * Legato @ref c_signals include file.
197  *
198  * Copyright (C) Sierra Wireless Inc.
199  */
200 
201 #ifndef LEGATO_SIGNALS_INCLUDE_GUARD
202 #define LEGATO_SIGNALS_INCLUDE_GUARD
203 
204 
205 //--------------------------------------------------------------------------------------------------
206 /**
207  * Prototype for the signal event handler functions.
208  */
209 //--------------------------------------------------------------------------------------------------
210 typedef void (*le_sig_EventHandlerFunc_t)
211 (
212  int sigNum ///< [IN] The signal that was received.
213 );
214 
215 
216 //--------------------------------------------------------------------------------------------------
217 /**
218  * Blocks a signal in the calling thread.
219  *
220  * Signals that an event handler will be set for must be blocked for all threads in the process. To
221  * ensure that the signals are blocked in all threads call this function in the process' first
222  * thread, all subsequent threads will inherit the signal mask.
223  *
224  * @note Does not return on failure.
225  */
226 //--------------------------------------------------------------------------------------------------
227 void le_sig_Block
228 (
229  int sigNum ///< [IN] Signal to block.
230 );
231 
232 
233 //--------------------------------------------------------------------------------------------------
234 /**
235  * Sets a signal event handler for the calling thread. Each signal can only have a single event
236  * handler per thread. The most recent event handler set will be called when the signal is
237  * received. sigEventHandler can be set to NULL to remove a previously set handler.
238  *
239  * @note sigNum Cannot be SIGKILL or SIGSTOP or any program error signals: SIGFPE, SIGILL,
240  * SIGSEGV, SIGBUS, SIGABRT, SIGIOT, SIGTRAP, SIGEMT, SIGSYS.
241  *
242  * @note Does not return on failure.
243  */
244 //--------------------------------------------------------------------------------------------------
246 (
247  int sigNum, ///< [IN] Signal to set the event handler for.
248  /// See parameter documentation in comments above.
249  le_sig_EventHandlerFunc_t sigEventHandler ///< [IN] Event handler to call when a signal is
250  /// received.
251 );
252 
253 
254 //--------------------------------------------------------------------------------------------------
255 /**
256  * Removes all signal event handlers for the calling thread and cleans up any resources used for
257  * signal events. This should be called before the thread exits.
258  */
259 //--------------------------------------------------------------------------------------------------
260 void le_sig_DeleteAll
261 (
262  void
263 );
264 
265 
266 //--------------------------------------------------------------------------------------------------
267 /**
268  * Install handler to show stack and signal informations on SIGSEGV/ILL/BUS/TRAP/FPE signals.
269  * Called automatically by main().
270  */
271 //--------------------------------------------------------------------------------------------------
273 (
274  void
275 );
276 
277 //--------------------------------------------------------------------------------------------------
278 /**
279  * Install a default handler to handle the SIGTERM signal.
280  * Called automatically by main().
281  */
282 //--------------------------------------------------------------------------------------------------
284 (
285  void
286 );
287 
288 
289 #endif // LEGATO_SIGNALS_INCLUDE_GUARD
void le_sig_DeleteAll(void)
void le_sig_Block(int sigNum)
void le_sig_InstallShowStackHandler(void)
void(* le_sig_EventHandlerFunc_t)(int sigNum)
Definition: le_signals.h:211
void le_sig_SetEventHandler(int sigNum, le_sig_EventHandlerFunc_t sigEventHandler)
void le_sig_InstallDefaultTermHandler(void)