2003-09-08 22:23:46 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: JRD Access Method
|
2003-10-16 10:51:06 +02:00
|
|
|
* MODULE: isc_ipc.cpp
|
2003-09-08 22:23:46 +02:00
|
|
|
* DESCRIPTION: Handing and posting of signals (POSIX)
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Interbase Public
|
|
|
|
* License Version 1.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy
|
|
|
|
* of the License at http://www.Inprise.com/IPL.html
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an
|
|
|
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
|
|
|
* or implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
|
|
|
*
|
|
|
|
* The Original Code was created by Inprise Corporation
|
|
|
|
* and its predecessors. Portions created by Inprise Corporation are
|
|
|
|
* Copyright (C) Inprise Corporation.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Contributor(s): ______________________________________.
|
|
|
|
* Solaris x86 changes - Konstantin Kuznetsov, Neil McCalden
|
|
|
|
*
|
|
|
|
* 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete ports:
|
|
|
|
* - EPSON, DELTA, IMP, NCR3000 and M88K
|
|
|
|
*
|
|
|
|
* 2002.10.27 Sean Leyne - Code Cleanup, removed obsolete "UNIXWARE" port
|
|
|
|
*
|
|
|
|
* 2002.10.28 Sean Leyne - Completed removal of obsolete "DGUX" port
|
|
|
|
*
|
|
|
|
* 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
|
|
|
|
*
|
|
|
|
* 2002.10.30 Sean Leyne - Removed support for obsolete "PC_PLATFORM" define
|
|
|
|
*
|
|
|
|
* 2003.08.27 Nickolay Samofatov - create POSIX version of this module
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "firebird.h"
|
2004-04-29 00:36:29 +02:00
|
|
|
#include <stdio.h>
|
2003-09-08 22:23:46 +02:00
|
|
|
#include <stdlib.h>
|
2003-11-04 00:59:24 +01:00
|
|
|
#include "../jrd/gdsassert.h"
|
2003-09-08 22:23:46 +02:00
|
|
|
#include "../jrd/common.h"
|
2003-11-11 13:19:20 +01:00
|
|
|
#include "gen/iberror.h"
|
2003-09-08 22:23:46 +02:00
|
|
|
#include "../jrd/isc.h"
|
|
|
|
#include "../jrd/gds_proto.h"
|
|
|
|
#include "../jrd/isc_proto.h"
|
|
|
|
#include "../jrd/os/isc_i_proto.h"
|
|
|
|
#include "../jrd/isc_s_proto.h"
|
2007-02-22 17:47:39 +01:00
|
|
|
#include "../common/classes/locks.h"
|
2008-01-23 16:52:40 +01:00
|
|
|
#include "../common/classes/init.h"
|
2003-09-08 22:23:46 +02:00
|
|
|
|
|
|
|
#ifdef HAVE_VFORK_H
|
|
|
|
#include <vfork.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_STRING_H
|
|
|
|
#include <string.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/file.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_SIGNAL_H
|
|
|
|
#include <signal.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_SIGNAL_H
|
|
|
|
#include <sys/signal.h>
|
|
|
|
#endif
|
|
|
|
|
2003-10-14 15:10:05 +02:00
|
|
|
#ifdef HAVE_SYS_SIGINFO_H
|
|
|
|
#include <sys/siginfo.h>
|
|
|
|
#endif
|
|
|
|
|
2003-09-08 22:23:46 +02:00
|
|
|
#include <errno.h>
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef O_RDWR
|
|
|
|
#include <fcntl.h>
|
|
|
|
#endif
|
|
|
|
|
2004-05-03 00:50:48 +02:00
|
|
|
//#define LOCAL_SEMAPHORES 4
|
2003-09-08 22:23:46 +02:00
|
|
|
|
2004-05-24 19:31:47 +02:00
|
|
|
struct sig {
|
2003-10-16 10:51:06 +02:00
|
|
|
struct sig* sig_next;
|
2003-09-08 22:23:46 +02:00
|
|
|
int sig_signal;
|
|
|
|
union {
|
|
|
|
FPTR_VOID_PTR user;
|
2006-10-09 14:36:39 +02:00
|
|
|
void (*client1) (int);
|
|
|
|
void (*client3) (int, siginfo_t *, void *);
|
2003-09-08 22:23:46 +02:00
|
|
|
FPTR_INT_VOID_PTR informs;
|
|
|
|
FPTR_VOID untyped;
|
|
|
|
} sig_routine;
|
2003-10-16 10:51:06 +02:00
|
|
|
void* sig_arg;
|
2003-09-08 22:23:46 +02:00
|
|
|
USHORT sig_flags;
|
2006-10-09 14:36:39 +02:00
|
|
|
USHORT sig_w_siginfo;
|
2004-05-24 19:31:47 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef sig *SIG;
|
2003-09-08 22:23:46 +02:00
|
|
|
|
2004-05-14 01:20:50 +02:00
|
|
|
// flags
|
|
|
|
const USHORT SIG_user = 0; /* Our routine */
|
|
|
|
const USHORT SIG_client = 1; /* Not our routine */
|
|
|
|
const USHORT SIG_informs = 2; /* routine tells us whether to chain */
|
2003-09-08 22:23:46 +02:00
|
|
|
|
2004-05-14 01:20:50 +02:00
|
|
|
const SLONG SIG_informs_continue = 0; /* continue on signal processing */
|
|
|
|
const SLONG SIG_informs_stop = 1; /* stop signal processing */
|
2003-09-08 22:23:46 +02:00
|
|
|
|
|
|
|
|
2003-10-16 10:51:06 +02:00
|
|
|
static bool initialized_signals = false;
|
2003-09-08 22:23:46 +02:00
|
|
|
static SIG volatile signals = NULL;
|
|
|
|
static SLONG volatile overflow_count = 0;
|
|
|
|
|
2008-01-23 16:52:40 +01:00
|
|
|
static Firebird::GlobalPtr<Firebird::Mutex> sig_mutex;
|
2003-09-08 22:23:46 +02:00
|
|
|
|
|
|
|
static int process_id = 0;
|
|
|
|
|
|
|
|
|
2004-05-14 01:20:50 +02:00
|
|
|
const char* GDS_RELAY = "/bin/gds_relay";
|
2003-09-08 22:23:46 +02:00
|
|
|
|
|
|
|
static int volatile relay_pipe = 0;
|
|
|
|
|
|
|
|
|
2003-10-16 10:51:06 +02:00
|
|
|
static void cleanup(void* arg);
|
2007-01-20 15:45:45 +01:00
|
|
|
static bool isc_signal2(int signal, FPTR_VOID handler, void* arg, ULONG);
|
2003-10-16 10:51:06 +02:00
|
|
|
static SLONG overflow_handler(void* arg);
|
2006-10-09 14:36:39 +02:00
|
|
|
static SIG que_signal(int signal, FPTR_VOID handler, void* arg, int flags, bool w_siginfo);
|
2003-09-08 22:23:46 +02:00
|
|
|
|
2006-10-09 14:36:39 +02:00
|
|
|
static void CLIB_ROUTINE signal_action(int number, siginfo_t *siginfo, void *context);
|
2003-09-08 22:23:46 +02:00
|
|
|
|
|
|
|
#ifndef SIG_HOLD
|
|
|
|
#define SIG_HOLD SIG_DFL
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Not thread-safe
|
|
|
|
|
2003-11-06 04:03:36 +01:00
|
|
|
ULONG isc_enter_count = 0;
|
2003-09-08 22:23:46 +02:00
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
void ISC_enter(void)
|
2003-09-08 22:23:46 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* I S C _ e n t e r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Enter ISC world from caller.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
/* Cancel our handler for SIGFPE - in case it was already there */
|
|
|
|
ISC_signal_cancel(SIGFPE, reinterpret_cast<FPTR_VOID_PTR>(overflow_handler), NULL);
|
|
|
|
|
|
|
|
/* Setup overflow handler - with chaining to any user handler */
|
|
|
|
isc_signal2(SIGFPE, reinterpret_cast<FPTR_VOID>(overflow_handler), NULL, SIG_informs);
|
|
|
|
|
|
|
|
#ifdef DEBUG_FPE_HANDLING
|
|
|
|
/* Debug code to simulate an FPE occuring during DB Operation */
|
|
|
|
if (overflow_count < 100)
|
|
|
|
(void) kill(getpid(), SIGFPE);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
void ISC_exit(void)
|
2003-09-08 22:23:46 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* I S C _ e x i t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Exit ISC world, return to caller.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
/* No longer attempt to handle overflow internally */
|
|
|
|
ISC_signal_cancel(SIGFPE, reinterpret_cast<FPTR_VOID_PTR>(overflow_handler), 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int ISC_kill(SLONG pid, SLONG signal_number)
|
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* I S C _ k i l l ( U N I X )
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Notify somebody else.
|
|
|
|
*
|
|
|
|
**************************************/
|
2007-01-20 15:45:45 +01:00
|
|
|
if (! pid)
|
|
|
|
pid = getpid();
|
|
|
|
|
2003-09-08 22:23:46 +02:00
|
|
|
for (;;) {
|
2003-10-16 10:51:06 +02:00
|
|
|
const int status = kill(pid, signal_number);
|
2003-09-08 22:23:46 +02:00
|
|
|
|
|
|
|
if (!status)
|
|
|
|
return status;
|
|
|
|
if (SYSCALL_INTERRUPTED(errno))
|
|
|
|
continue;
|
|
|
|
if (errno == EPERM)
|
|
|
|
break;
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Process is there, but we don't have the privilege to
|
|
|
|
send to him. */
|
2007-08-12 07:22:59 +02:00
|
|
|
|
2003-10-16 10:51:06 +02:00
|
|
|
int pipes[2];
|
|
|
|
|
2003-09-08 22:23:46 +02:00
|
|
|
if (!relay_pipe) {
|
2003-10-16 10:51:06 +02:00
|
|
|
TEXT process[MAXPATHLEN], arg[10];
|
2005-09-15 18:42:34 +02:00
|
|
|
|
2003-09-08 22:23:46 +02:00
|
|
|
gds__prefix(process, GDS_RELAY);
|
2005-09-15 18:42:34 +02:00
|
|
|
if (access(process, X_OK) != 0) {
|
|
|
|
// we don't have relay, therefore simply give meaningful diagnostic
|
|
|
|
gds__log("ISC_kill: process %d couldn't deliver signal %d "
|
|
|
|
"to process %d: permission denied", getpid(), signal_number, pid);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2003-09-08 22:23:46 +02:00
|
|
|
if (pipe(pipes)) {
|
2005-09-15 18:42:34 +02:00
|
|
|
gds__log("ISC_kill: error %d creating pipe to gds_relay", errno);
|
2003-09-08 22:23:46 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
sprintf(arg, "%d", pipes[0]);
|
|
|
|
if (!vfork()) {
|
|
|
|
execl(process, process, arg, 0);
|
|
|
|
gds__log("ISC_kill: error %d starting gds_relay %s", errno,
|
|
|
|
process);
|
|
|
|
_exit(0);
|
|
|
|
}
|
|
|
|
relay_pipe = pipes[1];
|
|
|
|
|
|
|
|
/* Don't need the READ pipe */
|
|
|
|
close(pipes[0]);
|
|
|
|
}
|
|
|
|
|
2003-10-16 10:51:06 +02:00
|
|
|
SLONG msg[3];
|
2003-09-08 22:23:46 +02:00
|
|
|
msg[0] = pid;
|
|
|
|
msg[1] = signal_number;
|
|
|
|
msg[2] = msg[0] ^ msg[1]; /* XOR for a consistancy check */
|
|
|
|
if (write(relay_pipe, msg, sizeof(msg)) != sizeof(msg)) {
|
|
|
|
gds__log("ISC_kill: write to relay_pipe failed %d", errno);
|
|
|
|
relay_pipe = 0; /* try to restart next time */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-20 15:45:45 +01:00
|
|
|
bool ISC_signal(int signal_number, FPTR_VOID_PTR handler, void* arg)
|
2003-09-08 22:23:46 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* I S C _ s i g n a l
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Multiplex multiple handers into single signal.
|
|
|
|
*
|
|
|
|
**************************************/
|
2007-01-20 15:45:45 +01:00
|
|
|
return isc_signal2(signal_number, reinterpret_cast<FPTR_VOID>(handler), arg, SIG_user);
|
2003-09-08 22:23:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-20 15:45:45 +01:00
|
|
|
static bool isc_signal2(
|
2003-09-08 22:23:46 +02:00
|
|
|
int signal_number,
|
2003-10-16 10:51:06 +02:00
|
|
|
FPTR_VOID handler, void* arg, ULONG flags)
|
2003-09-08 22:23:46 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* i s c _ s i g n a l 2 ( u n i x , W I N _ N T , O S 2 )
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Multiplex multiple handers into single signal.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
SIG sig;
|
|
|
|
|
|
|
|
/* The signal handler needs the process id */
|
|
|
|
if (!process_id)
|
|
|
|
process_id = getpid();
|
|
|
|
|
2008-01-23 16:52:40 +01:00
|
|
|
Firebird::MutexLockGuard guard(sig_mutex);
|
2003-09-08 22:23:46 +02:00
|
|
|
|
|
|
|
/* See if this signal has ever been cared about before */
|
|
|
|
|
|
|
|
for (sig = signals; sig; sig = sig->sig_next)
|
|
|
|
if (sig->sig_signal == signal_number)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* If it hasn't been attach our chain handler to the signal,
|
|
|
|
and queue up whatever used to handle it as a non-ISC
|
|
|
|
routine (they are invoked differently). Note that if
|
|
|
|
the old action was SIG_DFL, SIG_HOLD, SIG_IGN or our
|
|
|
|
multiplexor, there is no need to save it. */
|
|
|
|
|
2006-10-09 14:36:39 +02:00
|
|
|
bool old_sig_w_siginfo = false;
|
2007-01-20 15:45:45 +01:00
|
|
|
bool rc = false;
|
2003-09-08 22:23:46 +02:00
|
|
|
if (!sig) {
|
|
|
|
struct sigaction act, oact;
|
|
|
|
|
2006-10-09 14:36:39 +02:00
|
|
|
act.sa_sigaction = signal_action;
|
|
|
|
act.sa_flags = SA_RESTART | SA_SIGINFO;
|
2003-09-08 22:23:46 +02:00
|
|
|
sigemptyset(&act.sa_mask);
|
|
|
|
sigaddset(&act.sa_mask, signal_number);
|
|
|
|
sigaction(signal_number, &act, &oact);
|
2006-10-09 14:36:39 +02:00
|
|
|
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)
|
2004-03-08 19:06:20 +01:00
|
|
|
{
|
2006-10-09 14:36:39 +02:00
|
|
|
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);
|
2007-01-20 15:45:45 +01:00
|
|
|
rc = true;
|
2003-09-08 22:23:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Que up the new ISC signal handler routine */
|
|
|
|
|
2008-02-28 19:42:30 +01:00
|
|
|
que_signal(signal_number, handler, arg, flags, false);
|
2003-09-08 22:23:46 +02:00
|
|
|
|
2007-01-20 15:45:45 +01:00
|
|
|
return rc;
|
2003-09-08 22:23:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-05-29 15:34:54 +02:00
|
|
|
void ISC_signal_cancel(
|
2003-09-08 22:23:46 +02:00
|
|
|
int signal_number,
|
2003-10-16 10:51:06 +02:00
|
|
|
FPTR_VOID_PTR handler, void* arg)
|
2003-09-08 22:23:46 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* I S C _ s i g n a l _ c a n c e l
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Cancel a signal handler.
|
|
|
|
* If handler == NULL, cancel all handlers for a given signal.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
SIG sig;
|
2003-10-16 10:51:06 +02:00
|
|
|
volatile SIG* ptr;
|
2003-09-08 22:23:46 +02:00
|
|
|
|
2008-01-23 16:52:40 +01:00
|
|
|
Firebird::MutexLockGuard guard(sig_mutex);
|
2003-09-08 22:23:46 +02:00
|
|
|
|
|
|
|
for (ptr = &signals; sig = *ptr;) {
|
|
|
|
if (sig->sig_signal == signal_number &&
|
|
|
|
(handler == NULL ||
|
|
|
|
(sig->sig_routine.user == handler && sig->sig_arg == arg)))
|
|
|
|
{
|
|
|
|
*ptr = sig->sig_next;
|
|
|
|
gds__free(sig);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ptr = &(*ptr)->sig_next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-03 03:53:34 +02:00
|
|
|
void ISC_signal_init(void)
|
2003-09-08 22:23:46 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* I S C _ s i g n a l _ i n i t
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Initialize any system signal handlers.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
if (initialized_signals)
|
|
|
|
return;
|
|
|
|
|
2003-10-16 10:51:06 +02:00
|
|
|
initialized_signals = true;
|
2003-09-08 22:23:46 +02:00
|
|
|
|
|
|
|
overflow_count = 0;
|
|
|
|
gds__register_cleanup(cleanup, 0);
|
|
|
|
|
|
|
|
process_id = getpid();
|
|
|
|
|
|
|
|
isc_signal2(SIGFPE, reinterpret_cast<FPTR_VOID>(overflow_handler), 0, SIG_informs);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-16 10:51:06 +02:00
|
|
|
static void cleanup(void* arg)
|
2003-09-08 22:23:46 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* c l e a n u p
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Module level cleanup handler.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
signals = NULL;
|
|
|
|
|
|
|
|
process_id = 0;
|
|
|
|
|
2003-10-16 10:51:06 +02:00
|
|
|
initialized_signals = false;
|
2003-09-08 22:23:46 +02:00
|
|
|
}
|
|
|
|
|
2003-10-16 10:51:06 +02:00
|
|
|
static SLONG overflow_handler(void* arg)
|
2003-09-08 22:23:46 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* o v e r f l o w _ h a n d l e r
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Somebody overflowed. Ho hum.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
|
|
|
#ifdef DEBUG_FPE_HANDLING
|
2004-04-29 00:36:29 +02:00
|
|
|
fprintf(stderr, "overflow_handler (%x)\n", arg);
|
2003-09-08 22:23:46 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* 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
|
2006-10-09 14:36:39 +02:00
|
|
|
* ISC world, return back a code that tells signal_action to call any
|
2003-09-08 22:23:46 +02:00
|
|
|
* customer provided handler.
|
|
|
|
*/
|
|
|
|
if (isc_enter_count) {
|
|
|
|
++overflow_count;
|
|
|
|
#ifdef DEBUG_FPE_HANDLING
|
2004-04-29 00:36:29 +02:00
|
|
|
fprintf(stderr, "SIGFPE in isc code ignored %d\n",
|
2003-09-08 22:23:46 +02:00
|
|
|
overflow_count);
|
|
|
|
#endif
|
2006-10-09 14:36:39 +02:00
|
|
|
/* We've "handled" the FPE - let signal_action know not to chain
|
2003-09-08 22:23:46 +02:00
|
|
|
the signal to other handlers */
|
|
|
|
return SIG_informs_stop;
|
|
|
|
}
|
|
|
|
else {
|
2006-10-09 14:36:39 +02:00
|
|
|
/* We've NOT "handled" the FPE - let signal_action know to chain
|
2003-09-08 22:23:46 +02:00
|
|
|
the signal to other handlers */
|
|
|
|
return SIG_informs_continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-09 14:36:39 +02:00
|
|
|
static SIG que_signal(int signal_number,
|
|
|
|
FPTR_VOID handler,
|
|
|
|
void* arg,
|
|
|
|
int flags,
|
|
|
|
bool sig_w_siginfo)
|
2003-09-08 22:23:46 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
|
|
|
* q u e _ s i g n a l
|
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Que signal for later action.
|
|
|
|
*
|
|
|
|
**************************************/
|
2003-10-16 10:51:06 +02:00
|
|
|
SIG sig = (SIG) gds__alloc((SLONG) sizeof(struct sig));
|
2003-09-08 22:23:46 +02:00
|
|
|
/* FREE: unknown */
|
|
|
|
if (!sig) { /* NOMEM: */
|
|
|
|
DEV_REPORT("que_signal: out of memory");
|
|
|
|
return NULL; /* NOMEM: not handled, too difficult */
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG_GDS_ALLOC
|
|
|
|
/* This will only be freed when a signal handler is de-registered
|
|
|
|
* and we don't do that at process exit - so this not always
|
|
|
|
* a freed structure.
|
|
|
|
*/
|
|
|
|
gds_alloc_flag_unfreed((void *) sig);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
sig->sig_signal = signal_number;
|
|
|
|
sig->sig_routine.untyped = handler;
|
|
|
|
sig->sig_arg = arg;
|
|
|
|
sig->sig_flags = flags;
|
2006-10-09 14:36:39 +02:00
|
|
|
sig->sig_w_siginfo = sig_w_siginfo;
|
2003-09-08 22:23:46 +02:00
|
|
|
|
|
|
|
sig->sig_next = signals;
|
|
|
|
signals = sig;
|
|
|
|
|
|
|
|
return sig;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-10-09 14:36:39 +02:00
|
|
|
static void CLIB_ROUTINE signal_action(int number, siginfo_t *siginfo, void *context)
|
2003-09-08 22:23:46 +02:00
|
|
|
{
|
|
|
|
/**************************************
|
|
|
|
*
|
2006-10-09 14:36:39 +02:00
|
|
|
* s i g n a l _ a c t i o n
|
2003-09-08 22:23:46 +02:00
|
|
|
*
|
|
|
|
**************************************
|
|
|
|
*
|
|
|
|
* Functional description
|
|
|
|
* Checkin with various signal handlers.
|
|
|
|
*
|
|
|
|
**************************************/
|
|
|
|
|
2007-08-17 09:20:44 +02:00
|
|
|
// Invoke everybody who may have expressed an interest.
|
2003-09-08 22:23:46 +02:00
|
|
|
for (SIG sig = signals; sig; sig = sig->sig_next)
|
2006-10-09 14:36:39 +02:00
|
|
|
{
|
2003-09-08 22:23:46 +02:00
|
|
|
if (sig->sig_signal == number)
|
2006-10-09 14:36:39 +02:00
|
|
|
{
|
2003-09-08 22:23:46 +02:00
|
|
|
if (sig->sig_flags & SIG_client)
|
2006-10-09 14:36:39 +02:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2003-09-08 22:23:46 +02:00
|
|
|
/* Routine will tell us whether to chain the signal to other handlers */
|
|
|
|
if ((*sig->sig_routine.informs)(sig->sig_arg) == SIG_informs_stop)
|
2006-10-09 14:36:39 +02:00
|
|
|
{
|
2003-09-08 22:23:46 +02:00
|
|
|
break;
|
2006-10-09 14:36:39 +02:00
|
|
|
}
|
2003-09-08 22:23:46 +02:00
|
|
|
}
|
|
|
|
else
|
2006-10-09 14:36:39 +02:00
|
|
|
{
|
2003-09-08 22:23:46 +02:00
|
|
|
(*sig->sig_routine.user) (sig->sig_arg);
|
2006-10-09 14:36:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-09-08 22:23:46 +02:00
|
|
|
}
|
|
|
|
|