mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 18:03:04 +01:00
Fixed CORE-87
This commit is contained in:
parent
ca5ba8c731
commit
3ed7326ec1
@ -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 <stdio.h>
|
||||
@ -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<FPTR_VOID>(oact.sa_handler),
|
||||
NULL, SIG_client);
|
||||
que_signal(signal_number, old_sig_w_siginfo ?
|
||||
reinterpret_cast<FPTR_VOID>(oact.sa_sigaction) :
|
||||
reinterpret_cast<FPTR_VOID>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user