libassa 3.5.1
Loading...
Searching...
No Matches
SigHandlers.cpp
Go to the documentation of this file.
1// -*- c++ -*-
2//------------------------------------------------------------------------------
3// SigHandlers.cpp
4//------------------------------------------------------------------------------
5// Copyright (C) 1997-2002 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#include "assa/SigHandlers.h"
13
14using namespace ASSA;
15
16#if !defined(WIN32)
17
18//---------------------------------------------------------------------------
19// static declarations
20//---------------------------------------------------------------------------
21
23
24void
27{
28 trace_with_mask("SigHandlers::sighandlers_dispatch", SIGHAND);
29
30 DL((SIGHAND,"==> Received signal # %d\n", signum_));
32}
33
34int
36install (int signum_,
41{
42 /*
43 Retrieve current signal disposition. If 3rd party handler has
44 already been istalled, make CFUNC_Handler out of it, and put it in
45 the list with id=0.
46
47 Add new_hand_ to the list. Has global sighandlers_dispatcher not
48 been installed yet, install it too.
49 */
50
51 trace_with_mask("SigHandlers::install()", SIGHAND);
52
53 if (!in_range(signum_) == -1) {
54 EL((ASSAERR,"in_range (%s) failed\n",signum_));
55 return -1;
56 }
57
60
62
63 /*--- Retrieve current signal disposition ---*/
64
66 cd.retrieve_action(signum_);
67
68 /*
69 Check whether 3rd party software has already installed
70 signal handler.
71 */
72 if ( cd.handler() != (C_SIG_HANDLER) sighandlers_dispatcher &&
73 cd.handler() != SIG_IGN &&
74 cd.handler() != SIG_DFL )
75 {
76 /*
77 Looks like some other code got ahead of me and installed C-function
78 signal handler. Make a note of it.
79
80 Create EventHandler to hold 3rd party handler. This handler will be
81 deleted only by SigHandlers::remove (NULL), when application demanded
82 to remove all of the handlers.
83 */
84 DL((SIGHAND,"Detected 3rd party \"C\" handler!\n"));
85
86 cfhp = new CFUNC_Handler (cd.handler ());
87 handlist->cfunc_handler (cfhp);
88
89 /*
90 Insert 3rd party handler in list of handlers
91 for this signal.
92 */
93 DL((SIGHAND,"Adding 3rd party \"C\" handler\n"));
94
95 if ( handlist->insert (cfhp) == false ) {
96 EL((ASSAERR, "Failed to insert "\
97 "c_func_handler for signum %d\n", signum_));
98 delete (cfhp);
99 handlist->cfunc_handler (0);
100 return -1;
101 }
102 DL((SIGHAND,"Set size: %d\n", handlist->size () ));
103 }
104 /*--- Add new_hand_ to the list of handlers for signum_. ---*/
105
106 DL((SIGHAND,"Adding EventHandler to the list\n"));
107
108 if (handlist->insert (new_hand_) == false) {
109 /*---
110 I failed to install new handler and might have already
111 added 3rd party CFUNC_Handler to the list without altering
112 disposition - if that's true, clean up the list.
113 ---*/
114 EL((ASSAERR,"failed to add new_hand_ to handlers list\n"));
115
116 if (handlist->seen_cfunc_handler () &&
117 handlist->size() == 1)
118 {
119 handlist->erase ();
120 handlist->cfunc_handler (0);
121 }
122 return -1;
123 }
124 DL((SIGHAND,"Set size: %d\n", handlist->size () ));
125
126 /*--- Has sighandlers_dispatcher been already installed? ---*/
127
128 if (cd.handler() == (C_SIG_HANDLER) sighandlers_dispatcher) {
129 return 0;
130 }
131 DL((SIGHAND,"Installing 'sighandlers_dispatcher'\n"));
132
133 /*
134 Installing new disposition; if user forgot to give me one
135 then default will be used.
136 */
138
139 if (new_disp_ == 0) {
140 new_disp_ = &sa;
141 }
142
144
145 if (new_disp_->register_action (signum_, old_disp_) == -1) {
146 /*---
147 I failed to install sighandlers_dispatcher. Up to this
148 point, if application had conventional C handler installed,
149 it still remains active. Handlers list built so far is
150 meaningless - get rid of it. ---*/
151
152 EL((ASSAERR,"register_action() error\n"));
153
154 if (handlist->seen_cfunc_handler ()) {
155 handlist->erase ();
156 handlist->cfunc_handler (0);
157 delete cfhp;
158 }
159 handlist->erase (new_hand_);
160 return -1;
161 }
162 return 0;
163}
164
165int
169
170{
171 trace_with_mask("SigHandlers::remove()", SIGHAND);
172
173 if (in_range (signum_)) {
174 EL((ASSAERR, "singum_ %d is out of range\n", signum_));
175 return -1;
176 }
177
178 CFUNC_Handler* Cfhp = NULL; // pointer to C-function event handler
179 EventHandler* ehp = NULL; // pointer to current event handler
180
182
183 if (eh_ == NULL) {
184 DL((SIGHAND,"Erasing the entire set\n"));
185 /*--- Erase an entire list. ---*/
186 handlist.erase ();
187 DL((SIGHAND,"Set size: %d\n", handlist.size ()));
188 }
189 else {
190 /*
191 Note: I cannot do erasure in the same loop for following reason:
192
193 According to Stroustrup (Section 17.4.1.7):
194 "After erase(), the iterator cannot be used again because
195 the element to which it pointed is no longer there."
196
197 According to STL Tutorial and Ref. Guide:
198 "The erase function invalidates all iterators to all
199 positions past the point of erasure."
200
201 That's why here we first take care of id recycling and heap memory
202 deallocation, and only then clean() the map all at once.
203 */
205
206 if ((it = handlist.find (eh_)) != handlist.end ()) {
207 DL((SIGHAND,"Removing EventHandler\n"));
208 ehp = (*it);
209 handlist.erase (it);
210 }
211 DL((SIGHAND,"Set size: %d\n", handlist.size () ));
212 }
213 /*--- If set is not empty, we're done ---*/
214 if (handlist.size ()) return 0;
215
216 /* If map was emptied out, install new disposition
217 with the 3rd party "C" function handler, if we had it.
218 */
220 if (new_disp_ == 0) new_disp_ = &null_sa;
221
222 DL((SIGHAND,"Handlers List is empty\n"));
223
224 if (handlist.seen_cfunc_handler ()) {
225 /*--- Put 3rd party handler into disposition ---*/
226 DL((SIGHAND,"Reinstalling \"C\" handler\n"));
227 Cfhp = handlist.cfunc_handler (0);
228 new_disp_->handler (Cfhp->handler ());
229 delete Cfhp;
230 }
231 /*--- Install new disposition ---*/
232 return new_disp_->register_action (signum_, old_disp_);
233}
234
235void
237dispatch (int signum_)
238{
239 trace_with_mask("SigHandlers::dispatch", SIGHAND);
240
241 /*---
242 For every element in the set that holds all EventHandlers for
243 given signum, call its respective handle_signal() member function.
244 ---*/
245
246 /*--- save errno ---*/
247 int errno_saved = errno;
248
252
253 for (it=handlist.begin(); it != handlist.end(); it++) {
254 ehp = *it;
255 if (ehp->handle_signal (signum_) == -1) {
256 /*---
257 this event handler reported error when handling
258 signum - remove it from the set
259 ---*/
260 handlist.erase (it);
261 }
262 }
263 /*--- restore errno ---*/
265}
266
267#endif // !defined(WIN32)
268
#define EL(X)
A macro for writing error message to the Logger.
Definition Logger.h:285
#define DL(X)
A macro for writing debug message to the Logger.
Definition Logger.h:273
#define trace_with_mask(s, m)
trace_with_mask() is used to trace function call chain in C++ program.
Definition Logger.h:437
void(* C_SIG_HANDLER)(int)
Definition SigAction.h:28
SigHandlers is a signal handlers manager.
A wrapper class to provide AutoPtr with reference semantics.
Definition AutoPtr.h:32
CFUNC_Handler class.
EventHandler class.
int in_range(int signum_)
Check that signum_ is in valid range.
SigHandlersList class.
static SigHandlersList * m_instance[NSIG]
Static map of signal numbers to SigHandlerLists.
static SigHandlersList * instance(int signum_)
Retrieve a pointer to the list of event handlers listening to signum_ signal delivery.
set< key_type, CompSHL >::iterator iterator
static void sighandlers_dispatcher(int signum_)
A wrapper around static SigHandlers::dispatch().
virtual int remove(int signum_, EventHandler *eh_, SigAction *new_disp_=0, SigAction *old_disp_=0)
Remove EventHandler from the list of registered handler for signum_.
virtual int install(int signum_, EventHandler *new_hand_, SigAction *new_disp_=0, EventHandler **old_hand_=0, SigAction *old_disp_=0)
Register EventHandler with dispatching system.
static void dispatch(int signum_)
The heart of SigHandlers class - this callback function is really registered with OS to catch all of ...
@ SIGHAND
Class SigHandler(s) messages
Definition LogMask.h:38
@ ASSAERR
ASSA and system errors
Definition LogMask.h:34