diff --git a/src/jrd/os/posix/isc_ipc.cpp b/src/jrd/os/posix/isc_ipc.cpp index c00bf7e86b..d2b58d54ad 100644 --- a/src/jrd/os/posix/isc_ipc.cpp +++ b/src/jrd/os/posix/isc_ipc.cpp @@ -36,7 +36,7 @@ * */ - /* $Id: isc_ipc.cpp,v 1.17 2005-09-15 16:42:34 alexpeshkoff Exp $ */ + /* $Id: isc_ipc.cpp,v 1.18 2006-10-09 12:36:39 alexpeshkoff Exp $ */ #include "firebird.h" #include @@ -91,12 +91,14 @@ struct sig { int sig_signal; union { FPTR_VOID_PTR user; - void (*client) (int); + void (*client1) (int); + void (*client3) (int, siginfo_t *, void *); FPTR_INT_VOID_PTR informs; FPTR_VOID untyped; } sig_routine; void* sig_arg; USHORT sig_flags; + USHORT sig_w_siginfo; }; typedef sig *SIG; @@ -129,9 +131,9 @@ static int volatile relay_pipe = 0; static void cleanup(void* arg); static void isc_signal2(int signal, FPTR_VOID handler, void* arg, ULONG); static SLONG overflow_handler(void* arg); -static SIG que_signal(int signal, FPTR_VOID handler, void* arg, int flags); +static SIG que_signal(int signal, FPTR_VOID handler, void* arg, int flags, bool w_siginfo); -static void CLIB_ROUTINE signal_handler(int number); +static void CLIB_ROUTINE signal_action(int number, siginfo_t *siginfo, void *context); #ifndef SIG_HOLD #define SIG_HOLD SIG_DFL @@ -355,36 +357,32 @@ static void isc_signal2( the old action was SIG_DFL, SIG_HOLD, SIG_IGN or our multiplexor, there is no need to save it. */ + bool old_sig_w_siginfo = false; if (!sig) { struct sigaction act, oact; - act.sa_handler = signal_handler; - act.sa_flags = SA_RESTART; + act.sa_sigaction = signal_action; + act.sa_flags = SA_RESTART | SA_SIGINFO; sigemptyset(&act.sa_mask); sigaddset(&act.sa_mask, signal_number); sigaction(signal_number, &act, &oact); - - if ( -#ifdef SA_SIGINFO - // Do not queue user handlers requesting information. - // There is no easy and portable way to support them. - // Either Firebird or application should be adjusted to use another signal - !(oact.sa_flags & SA_SIGINFO) && -#endif - oact.sa_handler != signal_handler && - oact.sa_handler != SIG_DFL && - oact.sa_handler != SIG_HOLD && - oact.sa_handler != SIG_IGN - ) + old_sig_w_siginfo = oact.sa_flags & SA_SIGINFO; + + if (oact.sa_sigaction != signal_action && + oact.sa_handler != SIG_DFL && + oact.sa_handler != SIG_HOLD && + oact.sa_handler != SIG_IGN) { - que_signal(signal_number, reinterpret_cast(oact.sa_handler), - NULL, SIG_client); + que_signal(signal_number, old_sig_w_siginfo ? + reinterpret_cast(oact.sa_sigaction) : + reinterpret_cast(oact.sa_handler), + NULL, SIG_client, old_sig_w_siginfo); } } /* Que up the new ISC signal handler routine */ - que_signal(signal_number, handler, arg, flags); + que_signal(signal_number, handler, arg, flags, old_sig_w_siginfo); THD_MUTEX_UNLOCK(&sig_mutex); } @@ -493,7 +491,7 @@ static SLONG overflow_handler(void* arg) /* If we're within ISC world (inside why-value) when the FPE occurs * we handle it (basically by ignoring it). If it occurs outside of - * ISC world, return back a code that tells signal_handler to call any + * ISC world, return back a code that tells signal_action to call any * customer provided handler. */ if (isc_enter_count) { @@ -502,20 +500,22 @@ static SLONG overflow_handler(void* arg) fprintf(stderr, "SIGFPE in isc code ignored %d\n", overflow_count); #endif - /* We've "handled" the FPE - let signal_handler know not to chain + /* We've "handled" the FPE - let signal_action know not to chain the signal to other handlers */ return SIG_informs_stop; } else { - /* We've NOT "handled" the FPE - let signal_handler know to chain + /* We've NOT "handled" the FPE - let signal_action know to chain the signal to other handlers */ return SIG_informs_continue; } } -static SIG que_signal( - int signal_number, - FPTR_VOID handler, void* arg, int flags) +static SIG que_signal(int signal_number, + FPTR_VOID handler, + void* arg, + int flags, + bool sig_w_siginfo) { /************************************** * @@ -546,6 +546,7 @@ static SIG que_signal( sig->sig_routine.untyped = handler; sig->sig_arg = arg; sig->sig_flags = flags; + sig->sig_w_siginfo = sig_w_siginfo; sig->sig_next = signals; signals = sig; @@ -554,11 +555,11 @@ static SIG que_signal( } -static void CLIB_ROUTINE signal_handler(int number) +static void CLIB_ROUTINE signal_action(int number, siginfo_t *siginfo, void *context) { /************************************** * - * s i g n a l _ h a n d l e r ( G E N E R I C ) + * s i g n a l _ a c t i o n * ************************************** * @@ -569,15 +570,33 @@ static void CLIB_ROUTINE signal_handler(int number) /* Invoke everybody who may have expressed an interest. */ for (SIG sig = signals; sig; sig = sig->sig_next) + { if (sig->sig_signal == number) + { if (sig->sig_flags & SIG_client) - (*sig->sig_routine.client)(number); - else if (sig->sig_flags & SIG_informs) { + { + if (sig->sig_w_siginfo) + { + (*sig->sig_routine.client3)(number, siginfo, context); + } + else + { + (*sig->sig_routine.client1)(number); + } + } + else if (sig->sig_flags & SIG_informs) + { /* Routine will tell us whether to chain the signal to other handlers */ if ((*sig->sig_routine.informs)(sig->sig_arg) == SIG_informs_stop) + { break; + } } else + { (*sig->sig_routine.user) (sig->sig_arg); + } + } + } }