1 // -*- c++ -*-
2 //---------------------------------------------------------------------------
3 //                            SigHandlersList.h
4 //------------------------------------------------------------------------------
5 //  Copyright (c) 1997 by Vladislav Grinchenko
6 //
7 //  Permission to use, copy, modify, and distribute this software
8 //  and its documentation for any purpose and without fee is hereby
9 //  granted, provided that the above copyright notice appear in all
10 //  copies.  The author makes no representations about the suitability
11 //  of this software for any purpose.  It is provided "as is" without
12 //  express or implied warranty.
13 //---------------------------------------------------------------------------
14 
15 #ifndef _SigHandlersList_h
16 #define _SigHandlersList_h
17 
18 #include <signal.h>
19 #include <errno.h>
20 #include <sys/time.h>
21 #include <sys/types.h>
22 
23 #include "assa/SigHandler.h"
24 
25 #include <set>
26 using std::set;
27 
28 namespace ASSA {
29 
30 #if !defined(WIN32)
31 
32 /** @file SigHandlersList.h
33 
34     SigHandlersList is a Singleton class that maps signal number to a set of
35 	EventHandlers listening for the delivery of the signal.
36 */
37 
38 /** CFUNC_Handler  class.
39 
40     CFUNC_Handler is a wrapper around C signal handler function.
41 	It wraps C signal handler function into EventHandler interface.
42 */
43 
44 class CFUNC_Handler : public EventHandler
45 {
46 public:
47 	CFUNC_Handler (C_SIG_HANDLER csigh_);
48 
49 	int           handle_signal (int signum_);
handler()50 	C_SIG_HANDLER handler       () { return m_c_sig_hand; }
51 
52 private:
53 	C_SIG_HANDLER m_c_sig_hand;
54 };
55 
56 /** SigHandlersList class.
57 
58 
59 	SigHandlersList class is used by SigHandlers class to keep track of
60 	EventHandlers installed to be called on signal's delivery. It is sort of
61 	global process map of signal numbers into corresponding sets of
62 	EventHandlers that are listening for signal delivery.
63 */
64 
65 class SigHandlersList
66 {
67 public:
68 	typedef EventHandler* key_type;
69 	typedef EventHandler* data_type;
70 
71 	struct CompSHL {
operatorCompSHL72 		bool operator () (const key_type c1_, const key_type c2_) const
73 		{
74 // This wouldn't fly on 64-bit machines, 'cause ptr size there is 8 bytes long
75 //			return int(c1_) < int(c2_);
76 //
77 			return (c1_ < c2_);
78 		}
79 	};
80 
81 	typedef set< key_type, CompSHL > set_t;
82 	typedef set< key_type, CompSHL >::iterator iterator;
83 
84 	/** Retrieve a pointer to the list of event handlers
85 	    listening to signum_ signal delivery.
86 	*/
87 	static SigHandlersList* instance (int signum_);
88 
89 	/// Destructor
90 	~SigHandlersList ();
91 
92 	/// Is list empty
93 	bool empty () const;
94 
95 	/// Size of the list
96 	size_t size () const;
97 
98 	/** Add an event handler data_ to the list.
99 	    @return TRUE on success, FALSE on error.
100 	*/
101 	bool insert (data_type data_);
102 
103 	/** Find and remove event handler  key_  from the list.
104 	 */
105 	void erase (const key_type key_);
106 
107 	/** Remove an event handler pointed by iterator  it_
108 	    from the list.
109 	*/
110 	void erase (iterator it_);
111 
112 	/** Empty event handlers' list.
113 	 */
114 	void erase ();
115 
116 	/** Return an iterator pointing to the beginning of the list.
117 	 */
118 	iterator begin ();
119 
120 	/** Return an iterator pointing to the end of the list.
121 	 */
122 	iterator end ();
123 
124 	/** Find event handler by its pointer key_.
125 	    @return Iterator to the element.
126 	*/
127 	iterator find (const key_type key_);
128 
129 	/** Save 3rd party C function handler to remember.
130 	    @param cfp_ New 3rd party C function handler. If it is NULL,
131 	    then seen_cfh flag is set to FALSE.
132 	    @return old 3rd party C function handler.
133 	*/
134 	CFUNC_Handler* cfunc_handler (CFUNC_Handler* cfp_);
135 
136 	/** Retrieve pointer to 3rd party C function handler.
137 	    @return 3rd party C function handler.
138 	*/
139 	CFUNC_Handler* cfunc_handler () const;
140 
141 	/** Indicate whether 3rd party C function handler was installed.
142 	    @param ft_ TRUE if was, FALSE if not.
143 	*/
144 	void seen_cfunc_handler (bool ft_);
145 
146 	/** @return TRUE if we've seen 3rd party C function handler;
147 	    FALSE otherwise.
148 	*/
149 	bool seen_cfunc_handler () const;
150 
151 protected:
152 	SigHandlersList ();		// Singleton
153 	SigHandlersList (const SigHandlersList& map_); // prohibit copying
154 	SigHandlersList& operator= (const SigHandlersList& map_);
155 
156 public:
157 	/** Static map of signal numbers to SigHandlerLists.
158 	 */
159 	static SigHandlersList* m_instance[NSIG];
160 
161 private:
162 	/// Set of all event handlers registered for this signal.
163 	set_t*         m_set;
164 
165 	/** If true this flag indicates that 3rd party event handler
166 	    has already been installed prior taking control by SigHandlers
167 	    manager.
168 	*/
169 	int            m_seen_cfh;
170 
171 	/** Pointer to the 3rd party signal handler in the set
172 	*/
173 	CFUNC_Handler*  m_cfhp;
174 };
175 
176 //-------------------------------------------------------------------------
177 //----------------------- SigHandlersList Inlines -------------------------
178 //-------------------------------------------------------------------------
179 
180 inline
181 SigHandlersList::
SigHandlersList()182 SigHandlersList ()
183 	: m_seen_cfh (false), m_cfhp (NULL)
184 {
185 	trace_with_mask("SigHandlersList::SigHandlersList", SIGHAND);
186 
187 	m_set = new set_t;
188 }
189 
190 inline
191 SigHandlersList::
~SigHandlersList()192 ~SigHandlersList ()
193 {
194 	trace_with_mask("SigHandlersList::~SigHandlersList", SIGHAND);
195 
196 	erase ();
197 	delete m_set;
198 	m_set = NULL;
199 }
200 
201 inline  SigHandlersList*
202 SigHandlersList::
instance(int signum_)203 instance (int signum_)
204 {
205 	trace_with_mask("SigHandlersList::instance", SIGHAND);
206 
207 	DL((APP, "m_instance[%d] = 0x%x\n", signum_,
208 	    SigHandlersList::m_instance[signum_]));
209 
210 	if (SigHandlersList::m_instance[signum_] == 0) {
211 		DL((APP, "new SigHandlersList allocated\n"));
212 		SigHandlersList::m_instance[signum_] = new SigHandlersList();
213 	}
214 	return SigHandlersList::m_instance[signum_];
215 }
216 
217 inline bool
218 SigHandlersList::
empty()219 empty () const
220 {
221 	trace_with_mask("SigHandlersList::empty", SIGHAND);
222 
223 	// true if map is empty, false otherwise
224 
225 	return m_set->empty ();
226 }
227 
228 inline size_t
229 SigHandlersList::
size()230 size () const
231 {
232 	trace_with_mask("SigHandlersList::size", SIGHAND);
233 
234 	// return number of elements in the map
235 
236 	return m_set->size ();
237 }
238 
239 inline bool
240 SigHandlersList::
insert(data_type eh_)241 insert (data_type eh_)
242 {
243 	trace_with_mask("SigHandlersList::insert", SIGHAND);
244 
245 	/*---
246 	  Insert 'eh_' into the set. set::insert() returns a 'pair' object.
247 
248 	  If the set doesn't contain an element that matches 'eh_', insert a
249 	  copy of 'eh_' and returns a 'pair' whose first element is an
250 	  iterator positioned at the new element and second element is
251 	  'true'.
252 
253 	  If the set already contains an element that matches 'eh_', returns
254 	  a pair whose first element is an iterator positioned at the
255 	  existing element and second element is false!
256 	  ---*/
257 
258 	set_t::const_iterator it = m_set->find (eh_);
259 
260 	/*--- Not in the set ---*/
261 	if (it == m_set->end ()) {
262 		return (m_set->insert (eh_)).second;
263 	}
264 	/*--- Already in the set ---*/
265 	return true;
266 }
267 
268 inline void
269 SigHandlersList::
erase(const key_type key_)270 erase (const key_type key_)
271 {
272 	// return number of erased elements
273 	trace_with_mask("SigHandlersList::erase(key_)", SIGHAND);
274 
275 	m_set->erase (key_);
276 }
277 
278 inline void
279 SigHandlersList::
erase()280 erase ()
281 {
282 	// empty the map
283 	trace_with_mask("SigHandlersList::erase(void)", SIGHAND);
284 
285 	m_set->erase (m_set->begin(), m_set->end());
286 }
287 
288 inline void
289 SigHandlersList::
erase(iterator it_)290 erase(iterator it_)
291 {
292 	// erase element pointed by iterator
293 	trace_with_mask("SigHandlersList::erase(it_)", SIGHAND);
294 
295 	m_set->erase(it_);
296 }
297 
298 inline SigHandlersList::iterator
299 SigHandlersList::
begin()300 begin ()
301 {
302 	trace_with_mask("SigHandlersList::begin()", SIGHAND);
303 
304 	return m_set->begin ();
305 }
306 
307 inline SigHandlersList::iterator
308 SigHandlersList::
end()309 end ()
310 {
311 	trace_with_mask("SigHandlersList::end", SIGHAND);
312 
313 	return m_set->end ();
314 }
315 
316 inline SigHandlersList::iterator
317 SigHandlersList::
find(const key_type key_)318 find (const key_type key_)
319 {
320 	trace_with_mask("SigHandlersList::find", SIGHAND);
321 
322 	return m_set->find (key_);
323 }
324 
325 
326 inline CFUNC_Handler*
327 SigHandlersList::
cfunc_handler(CFUNC_Handler * cfhp_)328 cfunc_handler (CFUNC_Handler* cfhp_)
329 {
330 	trace_with_mask("SigHandlersList::cfunc_handler", SIGHAND);
331 
332 	CFUNC_Handler* old_cfhp = m_cfhp;
333 	m_cfhp = cfhp_;
334 	m_seen_cfh = cfhp_ == NULL ? false : true;
335 	return old_cfhp;
336 }
337 
338 inline CFUNC_Handler*
339 SigHandlersList::
cfunc_handler()340 cfunc_handler () const
341 {
342 	trace_with_mask("SigHandlersList::cfunc_handler", SIGHAND);
343 
344 	return m_cfhp;
345 }
346 
347 inline void
348 SigHandlersList::
seen_cfunc_handler(bool ft_)349 seen_cfunc_handler (bool ft_)
350 {
351 	trace_with_mask("SigHandlersList::seen_cfunc_handler", SIGHAND);
352 
353 	m_seen_cfh = ft_;
354 }
355 
356 inline bool
357 SigHandlersList::
seen_cfunc_handler()358 seen_cfunc_handler () const
359 {
360 	trace_with_mask("SigHandlersList::seen_cfunc_handler", SIGHAND);
361 
362 	return m_seen_cfh;
363 }
364 
365 //-------------------------------------------------------------------------
366 //------------------------ CFUNC_Handler Inlines --------------------------
367 //-------------------------------------------------------------------------
368 
369 inline
370 CFUNC_Handler::
CFUNC_Handler(C_SIG_HANDLER csigh_)371 CFUNC_Handler (C_SIG_HANDLER csigh_)
372 	: m_c_sig_hand (csigh_)
373 {
374 	trace_with_mask("CFUNC_Handler::CFUNC_Handler", SIGHAND);
375 }
376 
377 inline int
378 CFUNC_Handler::
handle_signal(int signum_)379 handle_signal (int signum_)
380 {
381 	trace_with_mask("CFUNC_Handler::handle_signal", SIGHAND);
382 
383 	if (m_c_sig_hand) {
384 		(*m_c_sig_hand)(signum_);
385 	}
386 	return 1;
387 }
388 
389 #endif // !defined(WIN32)
390 
391 } // end namespace ASSA
392 
393 #endif /* _SigHandlersList_h */
394 
395