postgresql/src/backend/libpq/pqsignal.c

147 lines
3.6 KiB
C

/*-------------------------------------------------------------------------
*
* pqsignal.c
* Backend signal(2) support (see also src/port/pqsignal.c)
*
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* src/backend/libpq/pqsignal.c
*
* ------------------------------------------------------------------------
*/
#include "postgres.h"
#include "libpq/pqsignal.h"
/* Global variables */
sigset_t UnBlockSig,
BlockSig,
StartupBlockSig;
/*
* Initialize BlockSig, UnBlockSig, and StartupBlockSig.
*
* BlockSig is the set of signals to block when we are trying to block
* signals. This includes all signals we normally expect to get, but NOT
* signals that should never be turned off.
*
* StartupBlockSig is the set of signals to block during startup packet
* collection; it's essentially BlockSig minus SIGTERM, SIGQUIT, SIGALRM.
*
* UnBlockSig is the set of signals to block when we don't want to block
* signals (is this ever nonzero??)
*/
void
pqinitmask(void)
{
sigemptyset(&UnBlockSig);
/* First set all signals, then clear some. */
sigfillset(&BlockSig);
sigfillset(&StartupBlockSig);
/*
* Unmark those signals that should never be blocked. Some of these signal
* names don't exist on all platforms. Most do, but might as well ifdef
* them all for consistency...
*/
#ifdef SIGTRAP
sigdelset(&BlockSig, SIGTRAP);
sigdelset(&StartupBlockSig, SIGTRAP);
#endif
#ifdef SIGABRT
sigdelset(&BlockSig, SIGABRT);
sigdelset(&StartupBlockSig, SIGABRT);
#endif
#ifdef SIGILL
sigdelset(&BlockSig, SIGILL);
sigdelset(&StartupBlockSig, SIGILL);
#endif
#ifdef SIGFPE
sigdelset(&BlockSig, SIGFPE);
sigdelset(&StartupBlockSig, SIGFPE);
#endif
#ifdef SIGSEGV
sigdelset(&BlockSig, SIGSEGV);
sigdelset(&StartupBlockSig, SIGSEGV);
#endif
#ifdef SIGBUS
sigdelset(&BlockSig, SIGBUS);
sigdelset(&StartupBlockSig, SIGBUS);
#endif
#ifdef SIGSYS
sigdelset(&BlockSig, SIGSYS);
sigdelset(&StartupBlockSig, SIGSYS);
#endif
#ifdef SIGCONT
sigdelset(&BlockSig, SIGCONT);
sigdelset(&StartupBlockSig, SIGCONT);
#endif
/* Signals unique to startup */
#ifdef SIGQUIT
sigdelset(&StartupBlockSig, SIGQUIT);
#endif
#ifdef SIGTERM
sigdelset(&StartupBlockSig, SIGTERM);
#endif
#ifdef SIGALRM
sigdelset(&StartupBlockSig, SIGALRM);
#endif
}
/*
* Set up a postmaster signal handler for signal "signo"
*
* Returns the previous handler.
*
* This is used only in the postmaster, which has its own odd approach to
* signal handling. For signals with handlers, we block all signals for the
* duration of signal handler execution. We also do not set the SA_RESTART
* flag; this should be safe given the tiny range of code in which the
* postmaster ever unblocks signals.
*
* pqinitmask() must have been invoked previously.
*
* On Windows, this function is just an alias for pqsignal()
* (and note that it's calling the code in src/backend/port/win32/signal.c,
* not src/port/pqsignal.c). On that platform, the postmaster's signal
* handlers still have to block signals for themselves.
*/
pqsigfunc
pqsignal_pm(int signo, pqsigfunc func)
{
#ifndef WIN32
struct sigaction act,
oact;
act.sa_handler = func;
if (func == SIG_IGN || func == SIG_DFL)
{
/* in these cases, act the same as pqsignal() */
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
}
else
{
act.sa_mask = BlockSig;
act.sa_flags = 0;
}
#ifdef SA_NOCLDSTOP
if (signo == SIGCHLD)
act.sa_flags |= SA_NOCLDSTOP;
#endif
if (sigaction(signo, &act, &oact) < 0)
return SIG_ERR;
return oact.sa_handler;
#else /* WIN32 */
return pqsignal(signo, func);
#endif
}