1 // -*- c++ -*-
2 //------------------------------------------------------------------------------
3 // SigAction.h
4 //------------------------------------------------------------------------------
5 // Copyright (c) 1997 by Vladislav Grinchenko
6 //
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Library General Public
9 // License as published by the Free Software Foundation; either
10 // version 2 of the License, or (at your option) any later version.
11 //------------------------------------------------------------------------------
12
13 #ifndef _SigAction_h
14 #define _SigAction_h
15
16 // System includes
17 //
18 #include <signal.h>
19 #include <errno.h>
20
21 #include "assa/Assure.h"
22 #include "assa/SigSet.h"
23
24 // some convenient typedefs
25 //
26 extern "C" {
27 typedef struct sigaction SIGACTION;
28 typedef void (*C_SIG_HANDLER)( int );
29 }
30
31 namespace ASSA {
32
33 #if !defined(WIN32)
34
35 /** @file SigAction.h
36
37 SigAction is a C++ wrapper around sigaction structure
38
39 Class SigAction implements a C++ wrapper around
40 struct sigaction. It class also provides a range of all possible
41 operation that can be performed on it, including sigaction(2) system call.
42
43 struct sigaction is defined as:
44
45 <pre>
46 struct sigaction {
47 void (*sa_handler) ();
48 sigset_t sa_mask;
49 int sa_flags;
50 void (*sa_sigaction) (int, siginfo_t*, void*);
51 };
52 </pre>
53
54 It is used to set all the details of what your process should do when
55 a signal arrives. It encapsulates the action to be taken on receipt
56 of a particular signal.
57
58 The most important member is sa_handler, which takes a pointer
59 to a function. This function will be invoked whenever the process gets
60 a particular POSIX.1 signal.
61
62 Some of the member function of SigAction class take a parameter
63 of type C_SIG_HANDLER.
64
65 It can be one of:
66 - "C" signal handling function (sa_handler above):\n
67 void sig_handler (int signum)
68 - SIG_ERR
69 - SIG DFL takes default signal action when caught
70 - SIG_IGN ignores signal (for those that can be ignored)
71
72 The sa_mask mask for the signal action specifies a set of signals
73 to be blocked while the signal handler is active.
74 On the entry into the signal handler,
75 that set of signals is added to a set of signals already being
76 blocked from delivery when the signal is delivered to the process.
77 In addition, the signal that caused the handler to be executed will also
78 be blocked (SIGSTOP and SIGKILL cannot be blocked - this is enforced
79 by the underlying OS).
80
81 Flags sa_flags in the set of flags ORed that allows to modify
82 the delivery of the signal.
83 POSIX.1 spec. defines only SA_NOCLDSTOP flag. All other
84 flags are system-dependent. Consult your local sigaction(2)
85 man page for details.
86
87 Because SigAction is a wrapper around sigaction(2),
88 after sig_handler returns (and before anything else), the OS
89 will reinstall current disposition for the signal. To reset signal's
90 disposition to SIG_DFL, SUN Solaris OS uses flag SA_RESETHAND, and Linux OS
91 uses SA_ONESHOT.
92 */
93
94 class SigAction
95 {
96 public:
97 /** Default constructor creates SigAction object
98 with null-action.
99 */
100 SigAction();
101
102 /** Construct a SigAction object with "C" signal
103 handler function. This constructor doesn't install any
104 actions - it is merely a shell for actiono to be installed
105 for any signal(s). Thus, you can reuse the same object for
106 number of differen signals.
107
108 @param handler_ "C" signal handler function to call.
109 @param sig_mask_ Set of signals to block while handler_
110 is active.
111 @param flags_ Controls behavior of signal handler (OS-specific:
112 see Available Options: section of documentation).
113 */
114 SigAction (C_SIG_HANDLER handler_,
115 SigSet* sig_mask_ = 0,
116 int flags_ = 0);
117
118 /** Construct a SigAction with "C" signal handler function
119 and change program's disposition for signum_
120 immediately.<p>
121 First argument is the "C" function. It cannot be a non-static
122 C++ class member function. This function pretty much simulates
123 C-like approach the the signal handling. For C++ member
124 function approach, see SigHandler & Co.
125
126 @param handler_ "C" signal handler function to call.
127 @param signum_ Signal which disposition is to change.
128 @param sig_mask_ Set of signals to block while handler_
129 is active.
130 @param flags_ Controls behavior of signal handler (OS-specific:
131 see Available Options: section of documentation).
132 */
133 SigAction (C_SIG_HANDLER handler_,
134 int signum_,
135 SigSet* sig_mask_ = 0,
136 int flags_ = 0);
137
138 /** Register this object as current disposition for signal
139 signum_, and store old disposition in oaction_,
140 if not NULL. This function installs C_SIG_HANDLER this
141 object represents, thus simulating C-like approach to signal
142 handling.
143
144 @param signum_ Signal which disposition to install.
145 @param oaction_ Placeholder for the old disposition.
146 @return 0 on success, -1 on error, with errno indicating
147 the error.
148 */
149 int register_action (int signum_, SigAction* oaction_ = 0);
150
151 /** Change object's disposition to oaction_, and install
152 it as current disposition for the signal signum_.
153
154 @param signum_ Signal which disposition to restore.
155 @param oaction_ Disposition to restore.
156 @return 0 on success, -1 on error, with errno indicating
157 the error.
158 */
159 int restore_action (int signum_, SigAction& oaction_);
160
161 /** Retrieve current disposition for the signal signum_
162 into this object.
163 @param signum_ Signal number
164 @return 0 on success, -1 on error, with errno indicating
165 the error.
166 */
167 int retrieve_action (int signum_);
168
169 /** Set sigaction structure to sa_
170 @param sa_ New value for internal struct sigaction.
171 */
172 void action (SIGACTION * sa_);
173
174 /** Retrieve current sigaction.
175 @return Pointer to an internal struct sigaction.
176 */
177 SIGACTION * action ();
178
179 /** Set signal flags to new_flags_.
180 @param new_flags_ New flags for this action.
181 */
182 void flags (int new_flags_);
183
184 /** Retrieve current flags.
185 @return Value of current flags for this action.
186 */
187 int flags ();
188
189 /** Set new signal mask mask_set_.
190 */
191 void mask (SigSet & mask_set_);
192
193 /** Retrieve current signal mask.
194 */
195 SigSet mask ();
196
197 /** Set new signal handler to function pointer sha_.
198 */
199 void handler (C_SIG_HANDLER sha_);
200
201 /** Retrieve current signal handler function.
202 */
203 C_SIG_HANDLER handler ();
204
205 /** Conversion operator that converts SigAction to a
206 pointer to the internal struct sigaction data
207 member for direct use with C-library functions.
208 */
209 operator SIGACTION *();
210
211 private:
212 /// sigaction structure itself
213 SIGACTION m_sa;
214 };
215
216 //-------------------------------------------------------------------------
217 //------------------------Inline functions---------------------------------
218 //-------------------------------------------------------------------------
219 inline
220 SigAction::
SigAction()221 SigAction ()
222 {
223 trace_with_mask("SigAction::SigAction", SIGACT);
224
225 m_sa.sa_flags = 0;
226 sigemptyset(&m_sa.sa_mask);
227 *(C_SIG_HANDLER*) &m_sa.sa_handler = (C_SIG_HANDLER) 0;
228 }
229
230 inline
231 SigAction::
SigAction(C_SIG_HANDLER handler_,SigSet * sig_mask_,int flags_)232 SigAction (C_SIG_HANDLER handler_,
233 SigSet* sig_mask_,
234 int flags_)
235 {
236 trace_with_mask("SigAction::SigAction(,,)", SIGACT);
237
238 m_sa.sa_flags = flags_;
239 if (sig_mask_ == NULL) {
240 sigemptyset(&m_sa.sa_mask);
241 }
242 else {
243 /*---
244 here, suppose to do bitwise structure assignment,
245 but does it really do so?
246 = *sig_mask_
247 = *(sig_mask_.operator *())
248 = *(SigSet *tmp = &sig_mask_.m_sa) ????
249 ---*/
250 m_sa.sa_mask = **sig_mask_;
251 }
252 *(C_SIG_HANDLER*) &m_sa.sa_handler = (C_SIG_HANDLER) handler_;
253 }
254
255 inline
256 SigAction::
SigAction(C_SIG_HANDLER handler_,int signum_,SigSet * sig_mask_,int flags_)257 SigAction (C_SIG_HANDLER handler_,
258 int signum_,
259 SigSet* sig_mask_,
260 int flags_)
261 {
262 trace_with_mask("SigAction::SigAction(,,,)", SIGACT);
263
264 m_sa.sa_flags = flags_;
265 if (sig_mask_ == NULL) {
266 sigemptyset(&m_sa.sa_mask);
267 }
268 else {
269 /*--- same problem as above... ---*/
270 m_sa.sa_mask = **sig_mask_;
271 }
272 *(C_SIG_HANDLER*) &m_sa.sa_handler = (C_SIG_HANDLER) handler_;
273
274 /*--- installing disposition... ---*/
275 sigaction (signum_, &m_sa, 0);
276 }
277
278 inline void
279 SigAction::
action(SIGACTION * sa_)280 action (SIGACTION* sa_)
281 {
282 trace_with_mask("SigAction::action", SIGACT);
283 m_sa = *sa_;
284 }
285
286 inline SIGACTION *
287 SigAction::
action()288 action ()
289 {
290 trace_with_mask("SigAction::action", SIGACT);
291
292 return &m_sa;
293 }
294
295 inline void
296 SigAction::
flags(int new_flags_)297 flags (int new_flags_)
298 {
299 trace_with_mask("void SigAction::flags()", SIGACT);
300
301 m_sa.sa_flags = new_flags_;
302 }
303
304 inline int
305 SigAction::
flags()306 flags ()
307 {
308 trace_with_mask("int SigAction::flags()", SIGACT);
309
310 return m_sa.sa_flags;
311 }
312
313 inline void
314 SigAction::
mask(SigSet & mask_set_)315 mask (SigSet & mask_set_)
316 {
317 trace_with_mask("void SigAction::mask()", SIGACT);
318
319 m_sa.sa_mask = *mask_set_;
320 }
321
322 inline SigSet
323 SigAction::
mask()324 mask ()
325 {
326 trace_with_mask("SigSet SigAction::mask()", SIGACT);
327
328 SigSet tmpset(&m_sa.sa_mask);
329 return tmpset;
330 }
331
332 inline void
333 SigAction::
handler(C_SIG_HANDLER sha_)334 handler (C_SIG_HANDLER sha_)
335 {
336 trace_with_mask("void SigAction::handler()", SIGACT);
337
338 *(C_SIG_HANDLER*) &m_sa.sa_handler = (C_SIG_HANDLER) sha_;
339 }
340
341 inline C_SIG_HANDLER
342 SigAction::
handler()343 handler ()
344 {
345 trace_with_mask("C_SIG_HANDLER SigAction::handler()", SIGACT);
346
347 return (C_SIG_HANDLER) m_sa.sa_handler;
348 }
349
350 inline
351 SigAction::operator SIGACTION * ()
352 {
353 trace_with_mask("SigAction::operator SIGACTION * ()", SIGACT);
354
355 return &m_sa;
356 }
357
358 inline int
359 SigAction::
register_action(int signum_,SigAction * oaction_)360 register_action (int signum_, SigAction* oaction_)
361 {
362 trace_with_mask("SigAction::register_action()", SIGACT);
363
364 /*--- place here recursive mutex lock to guard ... ---*/
365 struct sigaction *osa = oaction_ == 0 ? 0 : oaction_->action();
366 return sigaction(signum_, &m_sa, osa);
367 }
368
369 inline int
370 SigAction::
restore_action(int signum_,SigAction & oaction_)371 restore_action (int signum_, SigAction& oaction_)
372 {
373 trace_with_mask("SigAction::restore_action()", SIGACT);
374
375 m_sa = *oaction_.action();
376 return sigaction(signum_, &m_sa, 0);
377 }
378
379 inline int
380 SigAction::
retrieve_action(int signum_)381 retrieve_action (int signum_)
382 {
383 trace_with_mask("SigAction::retrieve_action()", SIGACT);
384
385 return sigaction(signum_, 0, &m_sa);
386 }
387
388 #endif // !defined(WIN32)
389
390 } // end namespace ASSA
391
392
393 #endif /* _SigAction_h */
394