Fixed typos
[ACE_TAO.git] / ACE / ace / Sig_Handler.cpp
blobe91de0b4fb4ba7327f61d3ac647bcc506458a33a
1 #include "ace/Sig_Handler.h"
2 #include "ace/Sig_Adapter.h"
3 #include "ace/Signal.h"
4 #include "ace/Recursive_Thread_Mutex.h"
5 #include "ace/Managed_Object.h"
6 #include "ace/Containers.h"
7 #include "ace/Guard_T.h"
9 #if !defined (__ACE_INLINE__)
10 #include "ace/Sig_Handler.inl"
11 #endif /* __ACE_INLINE__ */
13 #if defined (ACE_HAS_SIG_C_FUNC)
15 extern "C" void
16 ace_sig_handler_dispatch (int signum, siginfo_t *info, ucontext_t *context)
18 ACE_TRACE ("ace_sig_handler_dispatch");
19 ACE_Sig_Handler::dispatch (signum, info, context);
22 #define ace_signal_handler_dispatcher ACE_SignalHandler(ace_sig_handler_dispatch)
24 extern "C" void
25 ace_sig_handlers_dispatch (int signum, siginfo_t *info, ucontext_t *context)
27 ACE_TRACE ("ace_sig_handlers_dispatch");
28 ACE_Sig_Handlers::dispatch (signum, info, context);
31 #define ace_signal_handlers_dispatcher ACE_SignalHandler(ace_sig_handlers_dispatch)
33 #else
34 #define ace_signal_handler_dispatcher ACE_SignalHandler(ACE_Sig_Handler::dispatch)
36 #define ace_signal_handlers_dispatcher ACE_SignalHandler(ACE_Sig_Handlers::dispatch)
37 #endif /* ACE_HAS_SIG_C_FUNC */
39 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
41 /// Array of Event_Handlers that will handle the signals.
42 ACE_Event_Handler *ACE_Sig_Handler::signal_handlers_[ACE_NSIG];
44 /// Remembers if a signal has occurred.
45 sig_atomic_t ACE_Sig_Handler::sig_pending_ = 0;
47 ACE_ALLOC_HOOK_DEFINE(ACE_Sig_Handler)
49 ACE_Sig_Handler::~ACE_Sig_Handler (void)
51 for (int s = 1; s < ACE_NSIG; ++s)
52 if (ACE_Sig_Handler::signal_handlers_[s])
53 ACE_Sig_Handler::remove_handler_i (s);
56 void
57 ACE_Sig_Handler::dump (void) const
59 #if defined (ACE_HAS_DUMP)
60 ACE_TRACE ("ACE_Sig_Handler::dump");
61 #endif /* ACE_HAS_DUMP */
64 int
65 ACE_Sig_Handler::sig_pending (void)
67 ACE_TRACE ("ACE_Sig_Handler::sig_pending");
68 ACE_MT (ACE_Recursive_Thread_Mutex *lock =
69 ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
70 (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
71 ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, m, *lock, 0));
72 return ACE_Sig_Handler::sig_pending_ != 0;
75 void
76 ACE_Sig_Handler::sig_pending (int pending)
78 ACE_TRACE ("ACE_Sig_Handler::sig_pending");
80 ACE_MT (ACE_Recursive_Thread_Mutex *lock =
81 ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
82 (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
83 ACE_GUARD (ACE_Recursive_Thread_Mutex, m, *lock));
84 ACE_Sig_Handler::sig_pending_ = pending;
87 ACE_Event_Handler *
88 ACE_Sig_Handler::handler (int signum)
90 ACE_TRACE ("ACE_Sig_Handler::handler");
91 ACE_MT (ACE_Recursive_Thread_Mutex *lock =
92 ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
93 (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
94 ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, m, *lock, 0));
96 if (ACE_Sig_Handler::in_range (signum))
97 return ACE_Sig_Handler::signal_handlers_[signum];
98 else
99 return 0;
102 ACE_Event_Handler *
103 ACE_Sig_Handler::handler_i (int signum,
104 ACE_Event_Handler *new_sh)
106 ACE_TRACE ("ACE_Sig_Handler::handler_i");
108 if (ACE_Sig_Handler::in_range (signum))
110 ACE_Event_Handler *sh = ACE_Sig_Handler::signal_handlers_[signum];
112 ACE_Sig_Handler::signal_handlers_[signum] = new_sh;
113 return sh;
115 else
116 return 0;
119 ACE_Event_Handler *
120 ACE_Sig_Handler::handler (int signum,
121 ACE_Event_Handler *new_sh)
123 ACE_TRACE ("ACE_Sig_Handler::handler");
124 ACE_MT (ACE_Recursive_Thread_Mutex *lock =
125 ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
126 (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
127 ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, m, *lock, 0));
129 return ACE_Sig_Handler::handler_i (signum, new_sh);
132 /// Register an ACE_Event_Handler along with the corresponding SIGNUM.
133 /// This method does NOT acquire any locks, so it can be called from a
134 /// signal handler.
136 ACE_Sig_Handler::register_handler_i (int signum,
137 ACE_Event_Handler *new_sh,
138 ACE_Sig_Action *new_disp,
139 ACE_Event_Handler **old_sh,
140 ACE_Sig_Action *old_disp)
142 ACE_TRACE ("ACE_Sig_Handler::register_handler_i");
144 if (ACE_Sig_Handler::in_range (signum))
146 ACE_Sig_Action sa; // Define a "null" action.
147 ACE_Event_Handler *sh = ACE_Sig_Handler::handler_i (signum, new_sh);
149 // Return a pointer to the old <ACE_Sig_Handler> if the user
150 // asks for this.
151 if (old_sh != 0)
152 *old_sh = sh;
154 // Make sure that <new_disp> points to a valid location if the
155 // user doesn't care...
156 if (new_disp == 0)
157 new_disp = &sa;
159 new_disp->handler (ace_signal_handler_dispatcher);
160 #if !defined (ACE_HAS_LYNXOS4_SIGNALS)
161 new_disp->flags (new_disp->flags () | SA_SIGINFO);
162 #endif /* ACE_HAS_LYNXOS4_SIGNALS */
163 return new_disp->register_action (signum, old_disp);
165 else
166 return -1;
169 /// Register an ACE_Event_Handler along with the corresponding SIGNUM.
170 /// This method acquires a lock, so it can't be called from a signal
171 /// handler, e.g., <dispatch>.
173 ACE_Sig_Handler::register_handler (int signum,
174 ACE_Event_Handler *new_sh,
175 ACE_Sig_Action *new_disp,
176 ACE_Event_Handler **old_sh,
177 ACE_Sig_Action *old_disp)
179 ACE_TRACE ("ACE_Sig_Handler::register_handler");
180 ACE_MT (ACE_Recursive_Thread_Mutex *lock =
181 ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
182 (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
183 ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, m, *lock, -1));
185 return ACE_Sig_Handler::register_handler_i (signum,
186 new_sh,
187 new_disp,
188 old_sh,
189 old_disp);
193 ACE_Sig_Handler::remove_handler_i (int signum,
194 ACE_Sig_Action *new_disp,
195 ACE_Sig_Action *old_disp,
196 int)
198 ACE_TRACE ("ACE_Sig_Handler::remove_handler_i");
200 ACE_Sig_Action sa (SIG_DFL, (sigset_t *) 0); // Reset to default disposition.
202 if (new_disp == 0)
203 new_disp = &sa;
205 ACE_Event_Handler *eh = ACE_Sig_Handler::signal_handlers_[signum];
206 ACE_Sig_Handler::signal_handlers_[signum] = 0;
208 // Allow the event handler to close down if necessary.
209 if (eh)
211 eh->handle_close (ACE_INVALID_HANDLE,
212 ACE_Event_Handler::SIGNAL_MASK);
215 // Register either the new disposition or restore the default.
216 return new_disp->register_action (signum, old_disp);
219 /// Remove an ACE_Event_Handler.
221 ACE_Sig_Handler::remove_handler (int signum,
222 ACE_Sig_Action *new_disp,
223 ACE_Sig_Action *old_disp,
224 int)
226 ACE_TRACE ("ACE_Sig_Handler::remove_handler");
227 ACE_MT (ACE_Recursive_Thread_Mutex *lock =
228 ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
229 (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
230 ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, m, *lock, -1));
232 if (ACE_Sig_Handler::in_range (signum))
233 return ACE_Sig_Handler::remove_handler_i (signum, new_disp, old_disp);
235 return -1;
238 /// Master dispatcher function that gets called by a signal handler and
239 /// dispatches one handler...
240 void
241 ACE_Sig_Handler::dispatch (int signum,
242 siginfo_t *siginfo,
243 ucontext_t *ucontext)
245 ACE_TRACE ("ACE_Sig_Handler::dispatch");
247 // Save/restore errno.
248 ACE_Errno_Guard error (errno);
250 // We can't use the <sig_pending> call here because that acquires
251 // the lock, which is non-portable...
252 ACE_Sig_Handler::sig_pending_ = 1;
254 // Darn well better be in range since the OS dispatched this...
255 ACE_ASSERT (ACE_Sig_Handler::in_range (signum));
257 ACE_Event_Handler *eh = ACE_Sig_Handler::signal_handlers_[signum];
259 if (eh != 0)
261 if (eh->handle_signal (signum, siginfo, ucontext) == -1)
262 ACE_Sig_Handler::remove_handler_i (signum);
263 #if defined (ACE_WIN32)
264 else
265 // Win32 is weird in the sense that it resets the signal
266 // disposition to SIG_DFL after a signal handler is
267 // dispatched. Therefore, to workaround this "feature" we
268 // must re-register the <ACE_Event_Handler> with <signum>
269 // explicitly.
270 ACE_Sig_Handler::register_handler_i (signum, eh);
271 #endif /* ACE_WIN32*/
275 // ----------------------------------------
276 // The following classes are local to this file.
278 // There are bugs with HP/UX's C++ compiler that prevents this stuff
279 // from compiling...
280 #define ACE_MAX_SIGNAL_HANDLERS ((size_t) 20)
282 /// Keeps track of the id that uniquely identifies each registered
283 /// signal handler. This id can be used to cancel a timer via the
284 /// <remove_handler> method.
285 int ACE_Sig_Handlers::sigkey_ = 0;
287 /// If this is true then a 3rd party library has registered a
288 /// handler...
289 bool ACE_Sig_Handlers::third_party_sig_handler_ = false;
291 // Make life easier by defining typedefs...
292 typedef ACE_Fixed_Set <ACE_Event_Handler *, ACE_MAX_SIGNAL_HANDLERS> ACE_SIG_HANDLERS_SET;
293 typedef ACE_Fixed_Set_Iterator <ACE_Event_Handler *, ACE_MAX_SIGNAL_HANDLERS> ACE_SIG_HANDLERS_ITERATOR;
295 class ACE_Sig_Handlers_Set
297 public:
298 static ACE_SIG_HANDLERS_SET *instance (int signum);
300 private:
301 static ACE_SIG_HANDLERS_SET *sig_handlers_[ACE_NSIG];
304 /* static */
305 ACE_SIG_HANDLERS_SET *ACE_Sig_Handlers_Set::sig_handlers_[ACE_NSIG];
307 /* static */
308 ACE_SIG_HANDLERS_SET *
309 ACE_Sig_Handlers_Set::instance (int signum)
311 if (signum <= 0 || signum >= ACE_NSIG)
312 return 0; // This will cause problems...
313 else if (ACE_Sig_Handlers_Set::sig_handlers_[signum] == 0)
314 ACE_NEW_RETURN (ACE_Sig_Handlers_Set::sig_handlers_[signum],
315 ACE_SIG_HANDLERS_SET,
317 return ACE_Sig_Handlers_Set::sig_handlers_[signum];
320 ACE_ALLOC_HOOK_DEFINE(ACE_Sig_Handlers)
322 ACE_Sig_Handlers::ACE_Sig_Handlers (void)
326 void
327 ACE_Sig_Handlers::dump (void) const
329 #if defined (ACE_HAS_DUMP)
330 ACE_TRACE ("ACE_Sig_Handlers::dump");
331 #endif /* ACE_HAS_DUMP */
334 /// This is the method that does all the dirty work... The basic
335 /// structure of this method was devised by Detlef Becker.
337 ACE_Sig_Handlers::register_handler (int signum,
338 ACE_Event_Handler *new_sh,
339 ACE_Sig_Action *new_disp,
340 ACE_Event_Handler **,
341 ACE_Sig_Action *old_disp)
343 ACE_TRACE ("ACE_Sig_Handlers::register_handler");
344 ACE_MT (ACE_Recursive_Thread_Mutex *lock =
345 ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
346 (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
347 ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, m, *lock, -1));
349 if (ACE_Sig_Handler::in_range (signum))
351 ACE_Sig_Adapter *ace_sig_adapter = 0; // Our signal handler.
352 ACE_Sig_Adapter *extern_sh = 0; // An external signal handler.
353 ACE_Sig_Action sa;
355 // Get current signal disposition.
356 sa.retrieve_action (signum);
358 // Check whether we are already in control of the signal
359 // handling disposition...
361 if (!(sa.handler () == ace_signal_handlers_dispatcher
362 || sa.handler () == ACE_SignalHandler (SIG_IGN)
363 || sa.handler () == ACE_SignalHandler (SIG_DFL)))
365 // Drat, a 3rd party library has already installed a signal ;-(
367 // Upto here we never disabled RESTART_MODE. Thus,
368 // RESTART_MODE can only be changed by 3rd party libraries.
370 if (ACE_BIT_DISABLED (sa.flags (), SA_RESTART)
371 && ACE_Sig_Handlers::third_party_sig_handler_)
372 // Toggling is disallowed since we might break 3rd party
373 // code.
374 return -1;
376 // Note that we've seen a 3rd party handler...
377 ACE_Sig_Handlers::third_party_sig_handler_ = true;
379 // Create a new 3rd party disposition, remembering its
380 // preferred signal blocking etc...;
381 ACE_NEW_RETURN (extern_sh,
382 ACE_Sig_Adapter (sa,
383 ++ACE_Sig_Handlers::sigkey_),
384 -1);
385 // Add the external signal handler to the set of handlers
386 // for this signal.
387 if (ACE_Sig_Handlers_Set::instance (signum)->insert (extern_sh) == -1)
389 delete extern_sh;
390 return -1;
393 // Add our new handler at this point.
394 ACE_NEW_RETURN (ace_sig_adapter,
395 ACE_Sig_Adapter (new_sh,
396 ++ACE_Sig_Handlers::sigkey_),
397 -1);
399 // Add the ACE signal handler to the set of handlers for this
400 // signal (make sure it goes before the external one if there is
401 // one of these).
402 int result = ACE_Sig_Handlers_Set::instance (signum)->insert (ace_sig_adapter);
404 if (result == -1)
406 // We couldn't reinstall our handler, so let's pretend like
407 // none of this happened...
408 if (extern_sh)
410 ACE_Sig_Handlers_Set::instance (signum)->remove (extern_sh);
411 delete extern_sh;
413 delete ace_sig_adapter;
414 return -1;
416 // If ACE_Sig_Handlers::dispatch() was set we're done.
417 else if (sa.handler () == ace_signal_handlers_dispatcher)
418 return ace_sig_adapter->sigkey ();
420 // Otherwise, we need to register our handler function so that
421 // all signals will be dispatched through ACE.
422 else
424 // Make sure that new_disp points to a valid location if the
425 // user doesn't care...
426 if (new_disp == 0)
427 new_disp = &sa;
429 new_disp->handler (ace_signal_handlers_dispatcher);
431 // Default is to restart signal handlers.
432 new_disp->flags (new_disp->flags () | SA_RESTART);
433 #if !defined (ACE_HAS_LYNXOS4_SIGNALS)
434 new_disp->flags (new_disp->flags () | SA_SIGINFO);
435 #endif /* ACE_HAS_LYNXOS4_SIGNALS */
437 // Finally install (possibly reinstall) the ACE signal
438 // handler disposition with the SA_RESTART mode enabled.
439 if (new_disp->register_action (signum, old_disp) == -1)
441 // Yikes, lots of roll back at this point...
442 ACE_Sig_Handlers_Set::instance (signum)->remove (ace_sig_adapter);
443 delete ace_sig_adapter;
445 if (extern_sh)
447 ACE_Sig_Handlers_Set::instance (signum)->remove (extern_sh);
448 delete extern_sh;
450 return -1;
452 else // Return the signal key so that programs can cancel this
453 // handler if they want!
454 return ace_sig_adapter->sigkey ();
458 return -1;
461 /// Remove the ACE_Event_Handler currently associated with @a signum.
462 /// Install the new disposition (if given) and return the previous
463 /// disposition (if desired by the caller). Returns 0 on success and
464 // -1 if @a signum is invalid.
466 ACE_Sig_Handlers::remove_handler (int signum,
467 ACE_Sig_Action *new_disp,
468 ACE_Sig_Action *old_disp,
469 int sigkey)
471 ACE_TRACE ("ACE_Sig_Handlers::remove_handler");
472 ACE_MT (ACE_Recursive_Thread_Mutex *lock =
473 ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
474 (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
475 ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, m, *lock, -1));
477 if (ACE_Sig_Handler::in_range (signum))
479 ACE_SIG_HANDLERS_SET *handler_set =
480 ACE_Sig_Handlers_Set::instance (signum);
482 ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set);
484 // Iterate through the set of handlers for this signal.
485 for (ACE_Event_Handler **eh;
486 handler_iterator.next (eh) != 0;
489 // Type-safe downcast would be nice here...
490 ACE_Sig_Adapter *sh = (ACE_Sig_Adapter *) *eh;
492 // Remove the handler if (1) its key matches the key we've
493 // been told to remove or (2) if we've been told to remove
494 // *all* handlers (i.e., <sigkey> == -1).
495 if (sh->sigkey () == sigkey || sigkey == -1)
497 handler_set->remove (*eh);
498 delete *eh;
502 if (handler_set->size () == 0)
504 // If there are no more handlers left for a signal then
505 // register the new disposition or restore the default
506 // disposition.
507 ACE_Sig_Action sa (SIG_DFL, (sigset_t *) 0);
509 if (new_disp == 0)
510 new_disp = &sa;
512 return new_disp->register_action (signum, old_disp);
514 return 0;
516 else
517 return -1;
520 /// Master dispatcher function that gets called by a signal handler and
521 /// dispatches *all* the handlers...
522 void
523 ACE_Sig_Handlers::dispatch (int signum,
524 siginfo_t *siginfo,
525 ucontext_t *ucontext)
527 ACE_TRACE ("ACE_Sig_Handlers::dispatch");
528 // The following is #ifdef'd out because it's entirely non-portable
529 // to acquire a mutex in a signal handler...
530 #if 0
531 ACE_MT (ACE_Recursive_Thread_Mutex *lock =
532 ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
533 (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
534 ACE_TSS_Guard<ACE_Recursive_Thread_Mutex> m (*lock));
535 #endif /* 0 */
537 // Save/restore errno.
538 ACE_Errno_Guard error (errno);
540 ACE_Sig_Handler::sig_pending_ = 1;
542 // Darn well better be in range since the OS dispatched this...
543 ACE_ASSERT (ACE_Sig_Handler::in_range (signum));
545 ACE_SIG_HANDLERS_SET *handler_set =
546 ACE_Sig_Handlers_Set::instance (signum);
548 ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set);
550 for (ACE_Event_Handler **eh = 0;
551 handler_iterator.next (eh) != 0;
553 if ((*eh)->handle_signal (signum, siginfo, ucontext) == -1)
555 handler_set->remove (*eh);
556 delete *eh;
560 /// Return the first item in the list of handlers. Note that this will
561 /// trivially provide the same behavior as the ACE_Sig_Handler
562 /// version if there is only 1 handler registered!
563 ACE_Event_Handler *
564 ACE_Sig_Handlers::handler (int signum)
566 ACE_TRACE ("ACE_Sig_Handlers::handler");
567 ACE_SIG_HANDLERS_SET *handler_set =
568 ACE_Sig_Handlers_Set::instance (signum);
569 ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set);
570 ACE_Event_Handler **eh = 0;
571 handler_iterator.next (eh);
572 return *eh;
575 /// The following is a strange bit of logic that tries to give the same
576 /// semantics as what happens in ACE_Sig_Handler when we replace the
577 /// current signal handler with a new one. Note that if there is only
578 /// one signal handler the behavior will be identical. If there is
579 /// more than one handler then things get weird...
580 ACE_Event_Handler *
581 ACE_Sig_Handlers::handler (int signum, ACE_Event_Handler *new_sh)
583 ACE_TRACE ("ACE_Sig_Handlers::handler");
584 ACE_SIG_HANDLERS_SET *handler_set =
585 ACE_Sig_Handlers_Set::instance (signum);
586 ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set);
587 ACE_Event_Handler **eh = 0;
589 // Find the first handler...
590 handler_iterator.next (eh);
592 // ... then remove it from the set ...
593 handler_set->remove (*eh);
595 // ... and then insert the new signal handler into the beginning of
596 // the set (note, this is a bit too tied up in the implementation of
597 // ACE_Unbounded_Set...).
598 ACE_Sig_Adapter *temp = 0;
600 ACE_NEW_RETURN (temp,
601 ACE_Sig_Adapter (new_sh,
602 ++ACE_Sig_Handlers::sigkey_),
604 handler_set->insert (temp);
605 return *eh;
608 ACE_END_VERSIONED_NAMESPACE_DECL