Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / Sig_Handler.cpp
blob6dbdcb55a6c157a306a13b0012165e0ae63e901f
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 reinterpret_cast<ACE_SignalHandler> (reinterpret_cast<void*> ((ACE_Sig_Handler_Ex)ACE_Sig_Handler::dispatch))
36 #define ace_signal_handlers_dispatcher reinterpret_cast<ACE_SignalHandler> (reinterpret_cast<void*> ((ACE_Sig_Handler_Ex)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 ()
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 () 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 ()
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_Event_Handler if the user
150 // asks for this.
151 if (old_sh != 0)
152 *old_sh = sh;
154 // Make sure that @a 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 new_disp->flags (new_disp->flags () | SA_SIGINFO);
161 return new_disp->register_action (signum, old_disp);
163 else
164 return -1;
167 /// Register an ACE_Event_Handler along with the corresponding SIGNUM.
168 /// This method acquires a lock, so it can't be called from a signal
169 /// handler, e.g., <dispatch>.
171 ACE_Sig_Handler::register_handler (int signum,
172 ACE_Event_Handler *new_sh,
173 ACE_Sig_Action *new_disp,
174 ACE_Event_Handler **old_sh,
175 ACE_Sig_Action *old_disp)
177 ACE_TRACE ("ACE_Sig_Handler::register_handler");
178 ACE_MT (ACE_Recursive_Thread_Mutex *lock =
179 ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
180 (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
181 ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, m, *lock, -1));
183 return ACE_Sig_Handler::register_handler_i (signum,
184 new_sh,
185 new_disp,
186 old_sh,
187 old_disp);
191 ACE_Sig_Handler::remove_handler_i (int signum,
192 ACE_Sig_Action *new_disp,
193 ACE_Sig_Action *old_disp,
194 int)
196 ACE_TRACE ("ACE_Sig_Handler::remove_handler_i");
198 ACE_Sig_Action sa (SIG_DFL, (sigset_t *) 0); // Reset to default disposition.
200 if (new_disp == 0)
201 new_disp = &sa;
203 ACE_Event_Handler *eh = ACE_Sig_Handler::signal_handlers_[signum];
204 ACE_Sig_Handler::signal_handlers_[signum] = 0;
206 // Allow the event handler to close down if necessary.
207 if (eh)
209 eh->handle_close (ACE_INVALID_HANDLE,
210 ACE_Event_Handler::SIGNAL_MASK);
213 // Register either the new disposition or restore the default.
214 return new_disp->register_action (signum, old_disp);
217 /// Remove an ACE_Event_Handler.
219 ACE_Sig_Handler::remove_handler (int signum,
220 ACE_Sig_Action *new_disp,
221 ACE_Sig_Action *old_disp,
222 int)
224 ACE_TRACE ("ACE_Sig_Handler::remove_handler");
225 ACE_MT (ACE_Recursive_Thread_Mutex *lock =
226 ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
227 (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
228 ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, m, *lock, -1));
230 if (ACE_Sig_Handler::in_range (signum))
231 return ACE_Sig_Handler::remove_handler_i (signum, new_disp, old_disp);
233 return -1;
236 /// Master dispatcher function that gets called by a signal handler and
237 /// dispatches one handler...
238 void
239 ACE_Sig_Handler::dispatch (int signum, siginfo_t *siginfo, ucontext_t *ucontext)
241 ACE_TRACE ("ACE_Sig_Handler::dispatch");
243 // Save/restore errno.
244 ACE_Errno_Guard error (errno);
246 // We can't use the <sig_pending> call here because that acquires
247 // the lock, which is non-portable...
248 ACE_Sig_Handler::sig_pending_ = 1;
250 // Darn well better be in range since the OS dispatched this...
251 ACE_ASSERT (ACE_Sig_Handler::in_range (signum));
253 ACE_Event_Handler *eh = ACE_Sig_Handler::signal_handlers_[signum];
255 if (eh != 0)
257 if (eh->handle_signal (signum, siginfo, ucontext) == -1)
258 ACE_Sig_Handler::remove_handler_i (signum);
259 #if defined (ACE_WIN32)
260 else
261 // Win32 is weird in the sense that it resets the signal
262 // disposition to SIG_DFL after a signal handler is
263 // dispatched. Therefore, to workaround this "feature" we
264 // must re-register the <ACE_Event_Handler> with <signum>
265 // explicitly.
266 ACE_Sig_Handler::register_handler_i (signum, eh);
267 #endif /* ACE_WIN32*/
271 // ----------------------------------------
272 // The following classes are local to this file.
274 // There are bugs with HP/UX's C++ compiler that prevents this stuff
275 // from compiling...
276 #define ACE_MAX_SIGNAL_HANDLERS ((size_t) 20)
278 /// Keeps track of the id that uniquely identifies each registered
279 /// signal handler. This id can be used to cancel a timer via the
280 /// <remove_handler> method.
281 int ACE_Sig_Handlers::sigkey_ = 0;
283 /// If this is true then a 3rd party library has registered a
284 /// handler...
285 bool ACE_Sig_Handlers::third_party_sig_handler_ = false;
287 // Make life easier by defining typedefs...
288 using ACE_SIG_HANDLERS_SET = ACE_Fixed_Set<ACE_Event_Handler *, ((size_t)20)>;
289 using ACE_SIG_HANDLERS_ITERATOR = ACE_Fixed_Set_Iterator<ACE_Event_Handler *, ((size_t)20)>;
291 class ACE_Sig_Handlers_Set
293 public:
294 static ACE_SIG_HANDLERS_SET *instance (int signum);
296 private:
297 static ACE_SIG_HANDLERS_SET *sig_handlers_[ACE_NSIG];
300 /* static */
301 ACE_SIG_HANDLERS_SET *ACE_Sig_Handlers_Set::sig_handlers_[ACE_NSIG];
303 /* static */
304 ACE_SIG_HANDLERS_SET *
305 ACE_Sig_Handlers_Set::instance (int signum)
307 if (signum <= 0 || signum >= ACE_NSIG)
308 return 0; // This will cause problems...
309 else if (ACE_Sig_Handlers_Set::sig_handlers_[signum] == 0)
310 ACE_NEW_RETURN (ACE_Sig_Handlers_Set::sig_handlers_[signum],
311 ACE_SIG_HANDLERS_SET,
313 return ACE_Sig_Handlers_Set::sig_handlers_[signum];
316 ACE_ALLOC_HOOK_DEFINE(ACE_Sig_Handlers)
318 ACE_Sig_Handlers::ACE_Sig_Handlers ()
322 void
323 ACE_Sig_Handlers::dump () const
325 #if defined (ACE_HAS_DUMP)
326 ACE_TRACE ("ACE_Sig_Handlers::dump");
327 #endif /* ACE_HAS_DUMP */
330 /// This is the method that does all the dirty work... The basic
331 /// structure of this method was devised by Detlef Becker.
333 ACE_Sig_Handlers::register_handler (int signum,
334 ACE_Event_Handler *new_sh,
335 ACE_Sig_Action *new_disp,
336 ACE_Event_Handler **,
337 ACE_Sig_Action *old_disp)
339 ACE_TRACE ("ACE_Sig_Handlers::register_handler");
340 ACE_MT (ACE_Recursive_Thread_Mutex *lock =
341 ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
342 (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
343 ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, m, *lock, -1));
345 if (ACE_Sig_Handler::in_range (signum))
347 ACE_Sig_Adapter *ace_sig_adapter = nullptr; // Our signal handler.
348 ACE_Sig_Adapter *extern_sh = nullptr; // An external signal handler.
349 ACE_Sig_Action sa;
351 // Get current signal disposition.
352 sa.retrieve_action (signum);
354 // Check whether we are already in control of the signal
355 // handling disposition...
356 if (!(sa.handler () == ace_signal_handlers_dispatcher
357 || sa.handler () == ACE_SignalHandler (SIG_IGN)
358 || sa.handler () == ACE_SignalHandler (SIG_DFL)))
360 // Drat, a 3rd party library has already installed a signal ;-(
362 // Upto here we never disabled RESTART_MODE. Thus,
363 // RESTART_MODE can only be changed by 3rd party libraries.
364 if (ACE_BIT_DISABLED (sa.flags (), SA_RESTART)
365 && ACE_Sig_Handlers::third_party_sig_handler_)
366 // Toggling is disallowed since we might break 3rd party
367 // code.
368 return -1;
370 // Note that we've seen a 3rd party handler...
371 ACE_Sig_Handlers::third_party_sig_handler_ = true;
373 // Create a new 3rd party disposition, remembering its
374 // preferred signal blocking etc...;
375 ACE_NEW_RETURN (extern_sh,
376 ACE_Sig_Adapter (sa,
377 ++ACE_Sig_Handlers::sigkey_),
378 -1);
379 // Add the external signal handler to the set of handlers
380 // for this signal.
381 if (ACE_Sig_Handlers_Set::instance (signum)->insert (extern_sh) == -1)
383 delete extern_sh;
384 return -1;
387 // Add our new handler at this point.
388 ACE_NEW_RETURN (ace_sig_adapter,
389 ACE_Sig_Adapter (new_sh,
390 ++ACE_Sig_Handlers::sigkey_),
391 -1);
393 // Add the ACE signal handler to the set of handlers for this
394 // signal (make sure it goes before the external one if there is
395 // one of these).
396 int const result = ACE_Sig_Handlers_Set::instance (signum)->insert (ace_sig_adapter);
398 if (result == -1)
400 // We couldn't reinstall our handler, so let's pretend like
401 // none of this happened...
402 if (extern_sh)
404 ACE_Sig_Handlers_Set::instance (signum)->remove (extern_sh);
405 delete extern_sh;
407 delete ace_sig_adapter;
408 return -1;
410 // If ACE_Sig_Handlers::dispatch() was set we're done.
411 else if (sa.handler () == ace_signal_handlers_dispatcher)
412 return ace_sig_adapter->sigkey ();
414 // Otherwise, we need to register our handler function so that
415 // all signals will be dispatched through ACE.
416 else
418 // Make sure that new_disp points to a valid location if the
419 // user doesn't care...
420 if (new_disp == 0)
421 new_disp = &sa;
423 new_disp->handler (ace_signal_handlers_dispatcher);
425 // Default is to restart signal handlers.
426 new_disp->flags (new_disp->flags () | SA_RESTART);
427 new_disp->flags (new_disp->flags () | SA_SIGINFO);
429 // Finally install (possibly reinstall) the ACE signal
430 // handler disposition with the SA_RESTART mode enabled.
431 if (new_disp->register_action (signum, old_disp) == -1)
433 // Yikes, lots of roll back at this point...
434 ACE_Sig_Handlers_Set::instance (signum)->remove (ace_sig_adapter);
435 delete ace_sig_adapter;
437 if (extern_sh)
439 ACE_Sig_Handlers_Set::instance (signum)->remove (extern_sh);
440 delete extern_sh;
442 return -1;
444 else // Return the signal key so that programs can cancel this
445 // handler if they want!
446 return ace_sig_adapter->sigkey ();
450 return -1;
453 /// Remove the ACE_Event_Handler currently associated with @a signum.
454 /// Install the new disposition (if given) and return the previous
455 /// disposition (if desired by the caller). Returns 0 on success and
456 // -1 if @a signum is invalid.
458 ACE_Sig_Handlers::remove_handler (int signum,
459 ACE_Sig_Action *new_disp,
460 ACE_Sig_Action *old_disp,
461 int sigkey)
463 ACE_TRACE ("ACE_Sig_Handlers::remove_handler");
464 ACE_MT (ACE_Recursive_Thread_Mutex *lock =
465 ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
466 (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
467 ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, m, *lock, -1));
469 if (ACE_Sig_Handler::in_range (signum))
471 ACE_SIG_HANDLERS_SET *handler_set =
472 ACE_Sig_Handlers_Set::instance (signum);
474 ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set);
476 // Iterate through the set of handlers for this signal.
477 for (ACE_Event_Handler **eh;
478 handler_iterator.next (eh) != 0;
481 // Type-safe downcast would be nice here...
482 ACE_Sig_Adapter *sh = (ACE_Sig_Adapter *) *eh;
484 // Remove the handler if (1) its key matches the key we've
485 // been told to remove or (2) if we've been told to remove
486 // *all* handlers (i.e., <sigkey> == -1).
487 if (sh->sigkey () == sigkey || sigkey == -1)
489 handler_set->remove (*eh);
490 delete *eh;
494 if (handler_set->size () == 0)
496 // If there are no more handlers left for a signal then
497 // register the new disposition or restore the default
498 // disposition.
499 ACE_Sig_Action sa (SIG_DFL, (sigset_t *) 0);
501 if (new_disp == 0)
502 new_disp = &sa;
504 return new_disp->register_action (signum, old_disp);
506 return 0;
508 else
509 return -1;
512 /// Master dispatcher function that gets called by a signal handler and
513 /// dispatches *all* the handlers...
514 void
515 ACE_Sig_Handlers::dispatch (int signum, siginfo_t *siginfo, ucontext_t *ucontext)
517 ACE_TRACE ("ACE_Sig_Handlers::dispatch");
518 // The following is #ifdef'd out because it's entirely non-portable
519 // to acquire a mutex in a signal handler...
520 #if 0
521 ACE_MT (ACE_Recursive_Thread_Mutex *lock =
522 ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
523 (ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
524 ACE_TSS_Guard<ACE_Recursive_Thread_Mutex> m (*lock));
525 #endif /* 0 */
527 // Save/restore errno.
528 ACE_Errno_Guard error (errno);
530 ACE_Sig_Handler::sig_pending_ = 1;
532 // Darn well better be in range since the OS dispatched this...
533 ACE_ASSERT (ACE_Sig_Handler::in_range (signum));
535 ACE_SIG_HANDLERS_SET *handler_set =
536 ACE_Sig_Handlers_Set::instance (signum);
538 ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set);
540 for (ACE_Event_Handler **eh = 0;
541 handler_iterator.next (eh) != 0;
543 if ((*eh)->handle_signal (signum, siginfo, ucontext) == -1)
545 handler_set->remove (*eh);
546 delete *eh;
550 /// Return the first item in the list of handlers. Note that this will
551 /// trivially provide the same behavior as the ACE_Sig_Handler
552 /// version if there is only 1 handler registered!
553 ACE_Event_Handler *
554 ACE_Sig_Handlers::handler (int signum)
556 ACE_TRACE ("ACE_Sig_Handlers::handler");
557 ACE_SIG_HANDLERS_SET *handler_set =
558 ACE_Sig_Handlers_Set::instance (signum);
559 ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set);
560 ACE_Event_Handler **eh = 0;
561 handler_iterator.next (eh);
562 return *eh;
565 /// The following is a strange bit of logic that tries to give the same
566 /// semantics as what happens in ACE_Sig_Handler when we replace the
567 /// current signal handler with a new one. Note that if there is only
568 /// one signal handler the behavior will be identical. If there is
569 /// more than one handler then things get weird...
570 ACE_Event_Handler *
571 ACE_Sig_Handlers::handler (int signum, ACE_Event_Handler *new_sh)
573 ACE_TRACE ("ACE_Sig_Handlers::handler");
574 ACE_SIG_HANDLERS_SET *handler_set =
575 ACE_Sig_Handlers_Set::instance (signum);
576 ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set);
577 ACE_Event_Handler **eh = nullptr;
579 // Find the first handler...
580 handler_iterator.next (eh);
582 // ... then remove it from the set ...
583 handler_set->remove (*eh);
585 // ... and then insert the new signal handler into the beginning of
586 // the set (note, this is a bit too tied up in the implementation of
587 // ACE_Unbounded_Set...).
588 ACE_Sig_Adapter *temp = nullptr;
590 ACE_NEW_RETURN (temp,
591 ACE_Sig_Adapter (new_sh,
592 ++ACE_Sig_Handlers::sigkey_),
593 nullptr);
594 handler_set->insert (temp);
595 return *eh;
598 ACE_END_VERSIONED_NAMESPACE_DECL