libCom: Use SIG_IGN to ignore signals.

Simplified the code in osdSignal, also solves problems if a handler is
already installed that uses the 3-argument callback.
This commit is contained in:
Andrew Johnson
2010-09-23 15:09:03 -05:00
parent eacb6602bc
commit 5b860ec3ec

View File

@@ -1,5 +1,5 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
@@ -8,7 +8,7 @@
\*************************************************************************/
/*
* Author: J. Hill
* Authors: J. Hill, A. Johnson
*/
#include <signal.h>
@@ -17,81 +17,22 @@
#include <string.h>
#define epicsExportSharedSymbols
#include "epicsThread.h"
#include "epicsSignal.h"
#include "errlog.h"
extern "C" {
typedef void ( *pSigFunc ) ( int );
}
static pSigFunc pReplacedSigHupFunc = 0;
static pSigFunc pReplacedSigPipeFunc = 0;
/*
* localInstallSigHandler ()
*/
static void localInstallSigHandler ( int signalIn, pSigFunc pNewFunc,
pSigFunc * pReplacedFunc )
static void ignoreIfDefault(int signum, const char *name)
{
// install the handler
struct sigaction newAction;
struct sigaction oldAction;
newAction.sa_handler = pNewFunc;
int status = sigemptyset ( & newAction.sa_mask );
assert ( ! status );
newAction.sa_flags = 0;
status = sigaction ( signalIn, & newAction, & oldAction );
if ( status < 0 ) {
fprintf ( stderr, "%s: ignore install for signal %d failed beacuse %s\n",
__FILE__, signalIn, strerror ( errno ) );
struct sigaction curAction;
int status = sigaction(signum, NULL, &curAction);
if (status >= 0 &&
curAction.sa_handler == SIG_DFL) {
curAction.sa_handler = SIG_IGN;
status = sigaction(signum, &curAction, NULL);
}
else if ( oldAction.sa_handler != SIG_DFL &&
oldAction.sa_handler != SIG_IGN &&
oldAction.sa_handler != pNewFunc ) {
*pReplacedFunc = oldAction.sa_handler;
if (status < 0) {
fprintf(stderr, "%s: sigaction failed for %s, %s\n",
__FILE__, name, strerror(errno));
}
// enable delivery
sigset_t mask;
status = sigemptyset ( & mask );
assert ( ! status );
status = sigaddset ( & mask, signalIn );
assert ( ! status );
status = pthread_sigmask ( SIG_UNBLOCK, & mask, 0 );
assert ( ! status );
}
/*
* ignoreSigHup ()
*/
extern "C" {
static void ignoreSigHup ( int signal )
{
static volatile int reentered = 1;
if (--reentered == 0) {
if ( pReplacedSigHupFunc ) {
( *pReplacedSigHupFunc ) ( signal );
}
}
}
}
/*
* ignoreSigPipe ()
*/
extern "C" {
static void ignoreSigPipe ( int signal )
{
static volatile int reentered = 1;
if (--reentered == 0) {
if ( pReplacedSigPipeFunc ) {
( *pReplacedSigPipeFunc ) ( signal );
}
}
}
}
/*
@@ -99,8 +40,7 @@ static void ignoreSigPipe ( int signal )
*/
epicsShareFunc void epicsShareAPI epicsSignalInstallSigHupIgnore (void)
{
localInstallSigHandler ( SIGHUP,
ignoreSigHup, & pReplacedSigHupFunc );
ignoreIfDefault(SIGHUP, "SIGHUP");
}
/*
@@ -108,21 +48,10 @@ epicsShareFunc void epicsShareAPI epicsSignalInstallSigHupIgnore (void)
*/
epicsShareFunc void epicsShareAPI epicsSignalInstallSigPipeIgnore (void)
{
localInstallSigHandler ( SIGPIPE,
ignoreSigPipe, & pReplacedSigPipeFunc );
ignoreIfDefault(SIGPIPE, "SIGPIPE");
}
/*
* epicsSignalInstallSigAlarmIgnore ()
*/
epicsShareFunc void epicsShareAPI epicsSignalInstallSigAlarmIgnore ( void )
{
// Removed; this functionality was only required by HPUX,
// and it interferes with the posix timer API on Linux.
}
/*
* epicsSignalRaiseSigAlarm ()
*/
/* Disabled */
epicsShareFunc void epicsShareAPI epicsSignalInstallSigAlarmIgnore ( void ) {}
epicsShareFunc void epicsShareAPI epicsSignalRaiseSigAlarm
( struct epicsThreadOSD * /* threadId */ ) {}