mirror of
https://github.com/mangosfour/server.git
synced 2025-12-12 01:37:00 +00:00
615 lines
20 KiB
C++
615 lines
20 KiB
C++
// $Id: Sig_Handler.cpp 91626 2010-09-07 10:59:20Z johnnyw $
|
|
|
|
#include "ace/Sig_Handler.h"
|
|
#include "ace/Sig_Adapter.h"
|
|
#include "ace/Signal.h"
|
|
#include "ace/Recursive_Thread_Mutex.h"
|
|
#include "ace/Managed_Object.h"
|
|
#include "ace/Containers.h"
|
|
#include "ace/Guard_T.h"
|
|
|
|
#if !defined (__ACE_INLINE__)
|
|
#include "ace/Sig_Handler.inl"
|
|
#endif /* __ACE_INLINE__ */
|
|
|
|
|
|
|
|
#if defined (ACE_HAS_SIG_C_FUNC)
|
|
|
|
extern "C" void
|
|
ace_sig_handler_dispatch (int signum, siginfo_t *info, ucontext_t *context)
|
|
{
|
|
ACE_TRACE ("ace_sig_handler_dispatch");
|
|
ACE_Sig_Handler::dispatch (signum, info, context);
|
|
}
|
|
|
|
#define ace_signal_handler_dispatcher ACE_SignalHandler(ace_sig_handler_dispatch)
|
|
|
|
extern "C" void
|
|
ace_sig_handlers_dispatch (int signum, siginfo_t *info, ucontext_t *context)
|
|
{
|
|
ACE_TRACE ("ace_sig_handlers_dispatch");
|
|
ACE_Sig_Handlers::dispatch (signum, info, context);
|
|
}
|
|
|
|
#define ace_signal_handlers_dispatcher ACE_SignalHandler(ace_sig_handlers_dispatch)
|
|
|
|
#else
|
|
#define ace_signal_handler_dispatcher ACE_SignalHandler(ACE_Sig_Handler::dispatch)
|
|
|
|
#define ace_signal_handlers_dispatcher ACE_SignalHandler(ACE_Sig_Handlers::dispatch)
|
|
#endif /* ACE_HAS_SIG_C_FUNC */
|
|
|
|
|
|
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
|
|
|
|
// Array of Event_Handlers that will handle the signals.
|
|
ACE_Event_Handler *ACE_Sig_Handler::signal_handlers_[ACE_NSIG];
|
|
|
|
// Remembers if a signal has occurred.
|
|
sig_atomic_t ACE_Sig_Handler::sig_pending_ = 0;
|
|
|
|
|
|
ACE_ALLOC_HOOK_DEFINE(ACE_Sig_Handler)
|
|
|
|
ACE_Sig_Handler::~ACE_Sig_Handler (void)
|
|
{
|
|
}
|
|
|
|
void
|
|
ACE_Sig_Handler::dump (void) const
|
|
{
|
|
#if defined (ACE_HAS_DUMP)
|
|
ACE_TRACE ("ACE_Sig_Handler::dump");
|
|
#endif /* ACE_HAS_DUMP */
|
|
}
|
|
|
|
int
|
|
ACE_Sig_Handler::sig_pending (void)
|
|
{
|
|
ACE_TRACE ("ACE_Sig_Handler::sig_pending");
|
|
ACE_MT (ACE_Recursive_Thread_Mutex *lock =
|
|
ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
|
|
(ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
|
|
ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, m, *lock, 0));
|
|
return ACE_Sig_Handler::sig_pending_ != 0;
|
|
}
|
|
|
|
void
|
|
ACE_Sig_Handler::sig_pending (int pending)
|
|
{
|
|
ACE_TRACE ("ACE_Sig_Handler::sig_pending");
|
|
|
|
ACE_MT (ACE_Recursive_Thread_Mutex *lock =
|
|
ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
|
|
(ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
|
|
ACE_GUARD (ACE_Recursive_Thread_Mutex, m, *lock));
|
|
ACE_Sig_Handler::sig_pending_ = pending;
|
|
}
|
|
|
|
ACE_Event_Handler *
|
|
ACE_Sig_Handler::handler (int signum)
|
|
{
|
|
ACE_TRACE ("ACE_Sig_Handler::handler");
|
|
ACE_MT (ACE_Recursive_Thread_Mutex *lock =
|
|
ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
|
|
(ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
|
|
ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, m, *lock, 0));
|
|
|
|
if (ACE_Sig_Handler::in_range (signum))
|
|
return ACE_Sig_Handler::signal_handlers_[signum];
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
ACE_Event_Handler *
|
|
ACE_Sig_Handler::handler_i (int signum,
|
|
ACE_Event_Handler *new_sh)
|
|
{
|
|
ACE_TRACE ("ACE_Sig_Handler::handler_i");
|
|
|
|
if (ACE_Sig_Handler::in_range (signum))
|
|
{
|
|
ACE_Event_Handler *sh = ACE_Sig_Handler::signal_handlers_[signum];
|
|
|
|
ACE_Sig_Handler::signal_handlers_[signum] = new_sh;
|
|
return sh;
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
ACE_Event_Handler *
|
|
ACE_Sig_Handler::handler (int signum,
|
|
ACE_Event_Handler *new_sh)
|
|
{
|
|
ACE_TRACE ("ACE_Sig_Handler::handler");
|
|
ACE_MT (ACE_Recursive_Thread_Mutex *lock =
|
|
ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
|
|
(ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
|
|
ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, m, *lock, 0));
|
|
|
|
return ACE_Sig_Handler::handler_i (signum, new_sh);
|
|
}
|
|
|
|
// Register an ACE_Event_Handler along with the corresponding SIGNUM.
|
|
// This method does NOT acquire any locks, so it can be called from a
|
|
// signal handler.
|
|
|
|
int
|
|
ACE_Sig_Handler::register_handler_i (int signum,
|
|
ACE_Event_Handler *new_sh,
|
|
ACE_Sig_Action *new_disp,
|
|
ACE_Event_Handler **old_sh,
|
|
ACE_Sig_Action *old_disp)
|
|
{
|
|
ACE_TRACE ("ACE_Sig_Handler::register_handler_i");
|
|
|
|
if (ACE_Sig_Handler::in_range (signum))
|
|
{
|
|
ACE_Sig_Action sa; // Define a "null" action.
|
|
ACE_Event_Handler *sh = ACE_Sig_Handler::handler_i (signum, new_sh);
|
|
|
|
// Return a pointer to the old <ACE_Sig_Handler> if the user
|
|
// asks for this.
|
|
if (old_sh != 0)
|
|
*old_sh = sh;
|
|
|
|
// Make sure that <new_disp> points to a valid location if the
|
|
// user doesn't care...
|
|
if (new_disp == 0)
|
|
new_disp = &sa;
|
|
|
|
new_disp->handler (ace_signal_handler_dispatcher);
|
|
#if !defined (ACE_HAS_LYNXOS4_SIGNALS)
|
|
new_disp->flags (new_disp->flags () | SA_SIGINFO);
|
|
#endif /* ACE_HAS_LYNXOS4_SIGNALS */
|
|
return new_disp->register_action (signum, old_disp);
|
|
}
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
// Register an ACE_Event_Handler along with the corresponding SIGNUM.
|
|
// This method acquires a lock, so it can't be called from a signal
|
|
// handler, e.g., <dispatch>.
|
|
|
|
int
|
|
ACE_Sig_Handler::register_handler (int signum,
|
|
ACE_Event_Handler *new_sh,
|
|
ACE_Sig_Action *new_disp,
|
|
ACE_Event_Handler **old_sh,
|
|
ACE_Sig_Action *old_disp)
|
|
{
|
|
ACE_TRACE ("ACE_Sig_Handler::register_handler");
|
|
ACE_MT (ACE_Recursive_Thread_Mutex *lock =
|
|
ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
|
|
(ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
|
|
ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, m, *lock, -1));
|
|
|
|
return ACE_Sig_Handler::register_handler_i (signum,
|
|
new_sh,
|
|
new_disp,
|
|
old_sh,
|
|
old_disp);
|
|
}
|
|
|
|
// Remove an ACE_Event_Handler.
|
|
|
|
int
|
|
ACE_Sig_Handler::remove_handler (int signum,
|
|
ACE_Sig_Action *new_disp,
|
|
ACE_Sig_Action *old_disp,
|
|
int)
|
|
{
|
|
ACE_TRACE ("ACE_Sig_Handler::remove_handler");
|
|
ACE_MT (ACE_Recursive_Thread_Mutex *lock =
|
|
ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
|
|
(ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
|
|
ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, m, *lock, -1));
|
|
|
|
if (ACE_Sig_Handler::in_range (signum))
|
|
{
|
|
ACE_Sig_Action sa (SIG_DFL, (sigset_t *) 0); // Define the default disposition.
|
|
|
|
if (new_disp == 0)
|
|
new_disp = &sa;
|
|
|
|
ACE_Sig_Handler::signal_handlers_[signum] = 0;
|
|
|
|
// Register either the new disposition or restore the default.
|
|
return new_disp->register_action (signum, old_disp);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
// Master dispatcher function that gets called by a signal handler and
|
|
// dispatches one handler...
|
|
|
|
void
|
|
ACE_Sig_Handler::dispatch (int signum,
|
|
siginfo_t *siginfo,
|
|
ucontext_t *ucontext)
|
|
{
|
|
ACE_TRACE ("ACE_Sig_Handler::dispatch");
|
|
|
|
// Save/restore errno.
|
|
ACE_Errno_Guard error (errno);
|
|
|
|
// We can't use the <sig_pending> call here because that acquires
|
|
// the lock, which is non-portable...
|
|
ACE_Sig_Handler::sig_pending_ = 1;
|
|
|
|
// Darn well better be in range since the OS dispatched this...
|
|
ACE_ASSERT (ACE_Sig_Handler::in_range (signum));
|
|
|
|
ACE_Event_Handler *eh = ACE_Sig_Handler::signal_handlers_[signum];
|
|
|
|
if (eh != 0)
|
|
{
|
|
if (eh->handle_signal (signum, siginfo, ucontext) == -1)
|
|
{
|
|
// Define the default disposition.
|
|
ACE_Sig_Action sa ((ACE_SignalHandler) SIG_DFL, (sigset_t *) 0);
|
|
|
|
ACE_Sig_Handler::signal_handlers_[signum] = 0;
|
|
|
|
// Remove the current disposition by registering the default
|
|
// disposition.
|
|
sa.register_action (signum);
|
|
|
|
// Allow the event handler to close down if necessary.
|
|
eh->handle_close (ACE_INVALID_HANDLE,
|
|
ACE_Event_Handler::SIGNAL_MASK);
|
|
}
|
|
#if defined (ACE_WIN32)
|
|
else
|
|
// Win32 is weird in the sense that it resets the signal
|
|
// disposition to SIG_DFL after a signal handler is
|
|
// dispatched. Therefore, to workaround this "feature" we
|
|
// must re-register the <ACE_Event_Handler> with <signum>
|
|
// explicitly.
|
|
ACE_Sig_Handler::register_handler_i (signum, eh);
|
|
#endif /* ACE_WIN32*/
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------
|
|
// The following classes are local to this file.
|
|
|
|
// There are bugs with HP/UX's C++ compiler that prevents this stuff
|
|
// from compiling...
|
|
#define ACE_MAX_SIGNAL_HANDLERS ((size_t) 20)
|
|
|
|
// Keeps track of the id that uniquely identifies each registered
|
|
// signal handler. This id can be used to cancel a timer via the
|
|
// <remove_handler> method.
|
|
int ACE_Sig_Handlers::sigkey_ = 0;
|
|
|
|
// If this is true then a 3rd party library has registered a
|
|
// handler...
|
|
bool ACE_Sig_Handlers::third_party_sig_handler_ = false;
|
|
|
|
// Make life easier by defining typedefs...
|
|
typedef ACE_Fixed_Set <ACE_Event_Handler *, ACE_MAX_SIGNAL_HANDLERS> ACE_SIG_HANDLERS_SET;
|
|
typedef ACE_Fixed_Set_Iterator <ACE_Event_Handler *, ACE_MAX_SIGNAL_HANDLERS> ACE_SIG_HANDLERS_ITERATOR;
|
|
|
|
class ACE_Sig_Handlers_Set
|
|
{
|
|
public:
|
|
static ACE_SIG_HANDLERS_SET *instance (int signum);
|
|
|
|
private:
|
|
static ACE_SIG_HANDLERS_SET *sig_handlers_[ACE_NSIG];
|
|
};
|
|
|
|
/* static */
|
|
ACE_SIG_HANDLERS_SET *ACE_Sig_Handlers_Set::sig_handlers_[ACE_NSIG];
|
|
|
|
/* static */
|
|
ACE_SIG_HANDLERS_SET *
|
|
ACE_Sig_Handlers_Set::instance (int signum)
|
|
{
|
|
if (signum <= 0 || signum >= ACE_NSIG)
|
|
return 0; // This will cause problems...
|
|
else if (ACE_Sig_Handlers_Set::sig_handlers_[signum] == 0)
|
|
ACE_NEW_RETURN (ACE_Sig_Handlers_Set::sig_handlers_[signum],
|
|
ACE_SIG_HANDLERS_SET,
|
|
0);
|
|
return ACE_Sig_Handlers_Set::sig_handlers_[signum];
|
|
}
|
|
|
|
ACE_ALLOC_HOOK_DEFINE(ACE_Sig_Handlers)
|
|
|
|
void
|
|
ACE_Sig_Handlers::dump (void) const
|
|
{
|
|
#if defined (ACE_HAS_DUMP)
|
|
ACE_TRACE ("ACE_Sig_Handlers::dump");
|
|
#endif /* ACE_HAS_DUMP */
|
|
}
|
|
|
|
// This is the method that does all the dirty work... The basic
|
|
// structure of this method was devised by Detlef Becker.
|
|
|
|
int
|
|
ACE_Sig_Handlers::register_handler (int signum,
|
|
ACE_Event_Handler *new_sh,
|
|
ACE_Sig_Action *new_disp,
|
|
ACE_Event_Handler **,
|
|
ACE_Sig_Action *old_disp)
|
|
{
|
|
ACE_TRACE ("ACE_Sig_Handlers::register_handler");
|
|
ACE_MT (ACE_Recursive_Thread_Mutex *lock =
|
|
ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
|
|
(ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
|
|
ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, m, *lock, -1));
|
|
|
|
if (ACE_Sig_Handler::in_range (signum))
|
|
{
|
|
ACE_Sig_Adapter *ace_sig_adapter = 0; // Our signal handler.
|
|
ACE_Sig_Adapter *extern_sh = 0; // An external signal handler.
|
|
ACE_Sig_Action sa;
|
|
|
|
// Get current signal disposition.
|
|
sa.retrieve_action (signum);
|
|
|
|
// Check whether we are already in control of the signal
|
|
// handling disposition...
|
|
|
|
if (!(sa.handler () == ace_signal_handlers_dispatcher
|
|
|| sa.handler () == ACE_SignalHandler (SIG_IGN)
|
|
|| sa.handler () == ACE_SignalHandler (SIG_DFL)))
|
|
{
|
|
// Drat, a 3rd party library has already installed a signal ;-(
|
|
|
|
// Upto here we never disabled RESTART_MODE. Thus,
|
|
// RESTART_MODE can only be changed by 3rd party libraries.
|
|
|
|
if (ACE_BIT_DISABLED (sa.flags (), SA_RESTART)
|
|
&& ACE_Sig_Handlers::third_party_sig_handler_)
|
|
// Toggling is disallowed since we might break 3rd party
|
|
// code.
|
|
return -1;
|
|
|
|
// Note that we've seen a 3rd party handler...
|
|
ACE_Sig_Handlers::third_party_sig_handler_ = true;
|
|
|
|
// Create a new 3rd party disposition, remembering its
|
|
// preferred signal blocking etc...;
|
|
ACE_NEW_RETURN (extern_sh,
|
|
ACE_Sig_Adapter (sa,
|
|
++ACE_Sig_Handlers::sigkey_),
|
|
-1);
|
|
// Add the external signal handler to the set of handlers
|
|
// for this signal.
|
|
if (ACE_Sig_Handlers_Set::instance (signum)->insert (extern_sh) == -1)
|
|
{
|
|
delete extern_sh;
|
|
return -1;
|
|
}
|
|
}
|
|
// Add our new handler at this point.
|
|
ACE_NEW_RETURN (ace_sig_adapter,
|
|
ACE_Sig_Adapter (new_sh,
|
|
++ACE_Sig_Handlers::sigkey_),
|
|
-1);
|
|
// Add the ACE signal handler to the set of handlers for this
|
|
// signal (make sure it goes before the external one if there is
|
|
// one of these).
|
|
|
|
int result = ACE_Sig_Handlers_Set::instance (signum)->insert (ace_sig_adapter);
|
|
|
|
if (result == -1)
|
|
{
|
|
// We couldn't reinstall our handler, so let's pretend like
|
|
// none of this happened...
|
|
if (extern_sh)
|
|
{
|
|
ACE_Sig_Handlers_Set::instance (signum)->remove (extern_sh);
|
|
delete extern_sh;
|
|
}
|
|
delete ace_sig_adapter;
|
|
return -1;
|
|
}
|
|
// If ACE_Sig_Handlers::dispatch() was set we're done.
|
|
else if (sa.handler () == ace_signal_handlers_dispatcher)
|
|
return ace_sig_adapter->sigkey ();
|
|
|
|
// Otherwise, we need to register our handler function so that
|
|
// all signals will be dispatched through ACE.
|
|
else
|
|
{
|
|
// Make sure that new_disp points to a valid location if the
|
|
// user doesn't care...
|
|
if (new_disp == 0)
|
|
new_disp = &sa;
|
|
|
|
new_disp->handler (ace_signal_handlers_dispatcher);
|
|
|
|
// Default is to restart signal handlers.
|
|
new_disp->flags (new_disp->flags () | SA_RESTART);
|
|
#if !defined (ACE_HAS_LYNXOS4_SIGNALS)
|
|
new_disp->flags (new_disp->flags () | SA_SIGINFO);
|
|
#endif /* ACE_HAS_LYNXOS4_SIGNALS */
|
|
|
|
// Finally install (possibly reinstall) the ACE signal
|
|
// handler disposition with the SA_RESTART mode enabled.
|
|
if (new_disp->register_action (signum, old_disp) == -1)
|
|
{
|
|
// Yikes, lots of roll back at this point...
|
|
ACE_Sig_Handlers_Set::instance (signum)->remove (ace_sig_adapter);
|
|
delete ace_sig_adapter;
|
|
|
|
if (extern_sh)
|
|
{
|
|
ACE_Sig_Handlers_Set::instance (signum)->remove (extern_sh);
|
|
delete extern_sh;
|
|
}
|
|
return -1;
|
|
}
|
|
else // Return the signal key so that programs can cancel this
|
|
// handler if they want!
|
|
return ace_sig_adapter->sigkey ();
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
// Remove the ACE_Event_Handler currently associated with <signum>.
|
|
// Install the new disposition (if given) and return the previous
|
|
// disposition (if desired by the caller). Returns 0 on success and
|
|
// -1 if <signum> is invalid.
|
|
|
|
int
|
|
ACE_Sig_Handlers::remove_handler (int signum,
|
|
ACE_Sig_Action *new_disp,
|
|
ACE_Sig_Action *old_disp,
|
|
int sigkey)
|
|
{
|
|
ACE_TRACE ("ACE_Sig_Handlers::remove_handler");
|
|
ACE_MT (ACE_Recursive_Thread_Mutex *lock =
|
|
ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
|
|
(ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
|
|
ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, m, *lock, -1));
|
|
|
|
if (ACE_Sig_Handler::in_range (signum))
|
|
{
|
|
ACE_SIG_HANDLERS_SET *handler_set =
|
|
ACE_Sig_Handlers_Set::instance (signum);
|
|
|
|
ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set);
|
|
|
|
// Iterate through the set of handlers for this signal.
|
|
|
|
for (ACE_Event_Handler **eh;
|
|
handler_iterator.next (eh) != 0;
|
|
)
|
|
{
|
|
// Type-safe downcast would be nice here...
|
|
ACE_Sig_Adapter *sh = (ACE_Sig_Adapter *) *eh;
|
|
|
|
// Remove the handler if (1) its key matches the key we've
|
|
// been told to remove or (2) if we've been told to remove
|
|
// *all* handlers (i.e., <sigkey> == -1).
|
|
|
|
if (sh->sigkey () == sigkey || sigkey == -1)
|
|
{
|
|
handler_set->remove (*eh);
|
|
delete *eh;
|
|
}
|
|
}
|
|
|
|
if (handler_set->size () == 0)
|
|
{
|
|
// If there are no more handlers left for a signal then
|
|
// register the new disposition or restore the default
|
|
// disposition.
|
|
|
|
ACE_Sig_Action sa (SIG_DFL, (sigset_t *) 0);
|
|
|
|
if (new_disp == 0)
|
|
new_disp = &sa;
|
|
|
|
return new_disp->register_action (signum, old_disp);
|
|
}
|
|
return 0;
|
|
}
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
// Master dispatcher function that gets called by a signal handler and
|
|
// dispatches *all* the handlers...
|
|
|
|
void
|
|
ACE_Sig_Handlers::dispatch (int signum,
|
|
siginfo_t *siginfo,
|
|
ucontext_t *ucontext)
|
|
{
|
|
ACE_TRACE ("ACE_Sig_Handlers::dispatch");
|
|
// The following is #ifdef'd out because it's entirely non-portable
|
|
// to acquire a mutex in a signal handler...
|
|
#if 0
|
|
ACE_MT (ACE_Recursive_Thread_Mutex *lock =
|
|
ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
|
|
(ACE_Object_Manager::ACE_SIG_HANDLER_LOCK);
|
|
ACE_TSS_Guard<ACE_Recursive_Thread_Mutex> m (*lock));
|
|
#endif /* 0 */
|
|
|
|
// Save/restore errno.
|
|
ACE_Errno_Guard error (errno);
|
|
|
|
ACE_Sig_Handler::sig_pending_ = 1;
|
|
|
|
// Darn well better be in range since the OS dispatched this...
|
|
ACE_ASSERT (ACE_Sig_Handler::in_range (signum));
|
|
|
|
ACE_SIG_HANDLERS_SET *handler_set =
|
|
ACE_Sig_Handlers_Set::instance (signum);
|
|
|
|
ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set);
|
|
|
|
for (ACE_Event_Handler **eh = 0;
|
|
handler_iterator.next (eh) != 0;
|
|
)
|
|
if ((*eh)->handle_signal (signum, siginfo, ucontext) == -1)
|
|
{
|
|
handler_set->remove (*eh);
|
|
delete *eh;
|
|
}
|
|
}
|
|
|
|
// Return the first item in the list of handlers. Note that this will
|
|
// trivially provide the same behavior as the ACE_Sig_Handler
|
|
// version if there is only 1 handler registered!
|
|
|
|
ACE_Event_Handler *
|
|
ACE_Sig_Handlers::handler (int signum)
|
|
{
|
|
ACE_TRACE ("ACE_Sig_Handlers::handler");
|
|
ACE_SIG_HANDLERS_SET *handler_set =
|
|
ACE_Sig_Handlers_Set::instance (signum);
|
|
ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set);
|
|
ACE_Event_Handler **eh = 0;
|
|
handler_iterator.next (eh);
|
|
return *eh;
|
|
}
|
|
|
|
// The following is a strange bit of logic that tries to give the same
|
|
// semantics as what happens in ACE_Sig_Handler when we replace the
|
|
// current signal handler with a new one. Note that if there is only
|
|
// one signal handler the behavior will be identical. If there is
|
|
// more than one handler then things get weird...
|
|
|
|
ACE_Event_Handler *
|
|
ACE_Sig_Handlers::handler (int signum, ACE_Event_Handler *new_sh)
|
|
{
|
|
ACE_TRACE ("ACE_Sig_Handlers::handler");
|
|
ACE_SIG_HANDLERS_SET *handler_set =
|
|
ACE_Sig_Handlers_Set::instance (signum);
|
|
ACE_SIG_HANDLERS_ITERATOR handler_iterator (*handler_set);
|
|
ACE_Event_Handler **eh = 0;
|
|
|
|
// Find the first handler...
|
|
handler_iterator.next (eh);
|
|
|
|
// ... then remove it from the set ...
|
|
handler_set->remove (*eh);
|
|
|
|
// ... and then insert the new signal handler into the beginning of
|
|
// the set (note, this is a bit too tied up in the implementation of
|
|
// ACE_Unbounded_Set...).
|
|
ACE_Sig_Adapter *temp = 0;
|
|
|
|
ACE_NEW_RETURN (temp,
|
|
ACE_Sig_Adapter (new_sh,
|
|
++ACE_Sig_Handlers::sigkey_),
|
|
0);
|
|
handler_set->insert (temp);
|
|
return *eh;
|
|
}
|
|
|
|
ACE_END_VERSIONED_NAMESPACE_DECL
|