libassa
3.5.1
Main Page
Namespaces
Classes
Files
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Friends
Macros
assa
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
14
using namespace
ASSA;
15
16
#if !defined(WIN32)
17
18
//---------------------------------------------------------------------------
19
// static declarations
20
//---------------------------------------------------------------------------
21
22
SigHandlersList
*
SigHandlersList::m_instance
[NSIG];
23
24
void
25
SigHandlers::
26
sighandlers_dispatcher
(
int
signum_)
27
{
28
trace_with_mask
(
"SigHandlers::sighandlers_dispatch"
,
SIGHAND
);
29
30
DL
((
SIGHAND
,
"==> Recevied signal # %d\n"
, signum_));
31
dispatch
(signum_);
32
}
33
34
int
35
SigHandlers::
36
install
(
int
signum_,
37
EventHandler
* new_hand_,
38
SigAction
* new_disp_,
39
EventHandler
** old_hand_,
40
SigAction
* old_disp_)
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
58
CFUNC_Handler
* cfhp = NULL;
59
SigHandlersList
* handlist = NULL;
60
61
handlist =
SigHandlersList::instance
(signum_);
62
63
/*--- Retrieve current signal disposition ---*/
64
65
SigAction
cd;
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
*/
137
SigAction
sa ((
C_SIG_HANDLER
) SIG_DFL);
138
139
if
(new_disp_ == 0) {
140
new_disp_ = &sa;
141
}
142
143
new_disp_->
handler
((
C_SIG_HANDLER
)
sighandlers_dispatcher
);
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
165
int
166
SigHandlers::
167
remove
(
int
signum_,
EventHandler
* eh_,
168
SigAction
* new_disp_,
SigAction
* old_disp_)
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
181
SigHandlersList
& handlist = *(
SigHandlersList::instance
(signum_));
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
*/
204
SigHandlersList::iterator
it;
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
*/
219
SigAction
null_sa;
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
235
void
236
SigHandlers::
237
dispatch
(
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
249
SigHandlersList
& handlist = *(
SigHandlersList::instance
(signum_));
250
SigHandlersList::iterator
it;
251
EventHandler
* ehp;
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 ---*/
264
errno = errno_saved;
265
}
266
267
#endif // !defined(WIN32)
268
Generated on Tue Jun 19 2012 08:06:07 for libassa by
1.8.1.1