blob: 6f129e4b820f0b858917f76ff10895f0cfcbd4de [file] [log] [blame]
/*-------------------------------------------------------------------------
*
* pqsignal.c
* reliable BSD-style signal(2) routine stolen from RWW who stole it
* from Stevens...
*
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/libpq/pqsignal.c,v 1.47 2010/01/02 16:57:45 momjian Exp $
*
* NOTES
* This shouldn't be in libpq, but the monitor and some other
* things need it...
*
* A NOTE ABOUT SIGNAL HANDLING ACROSS THE VARIOUS PLATFORMS.
*
* pg_config.h defines the macro HAVE_POSIX_SIGNALS for some platforms and
* not for others. This file and pqsignal.h use that macro to decide
* how to handle signalling.
*
* signal(2) handling - this is here because it affects some of
* the frontend commands as well as the backend server.
*
* Ultrix and SunOS provide BSD signal(2) semantics by default.
*
* SVID2 and POSIX signal(2) semantics differ from BSD signal(2)
* semantics. We can use the POSIX sigaction(2) on systems that
* allow us to request restartable signals (SA_RESTART).
*
* Some systems don't allow restartable signals at all unless we
* link to a special BSD library.
*
* We devoutly hope that there aren't any systems that provide
* neither POSIX signals nor BSD signals. The alternative
* is to do signal-handler reinstallation, which doesn't work well
* at all.
* ------------------------------------------------------------------------*/
#include "postgres.h"
#include <signal.h>
#include "libpq/pqsignal.h"
#ifdef HAVE_SIGPROCMASK
sigset_t UnBlockSig,
BlockSig,
StartupBlockSig;
#else
int UnBlockSig,
BlockSig,
StartupBlockSig;
#endif
/*
* 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)
{
#ifdef HAVE_SIGPROCMASK
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
#else
/* Set the signals we want. */
UnBlockSig = 0;
BlockSig = sigmask(SIGQUIT) |
sigmask(SIGTERM) | sigmask(SIGALRM) |
/* common signals between two */
sigmask(SIGHUP) |
sigmask(SIGINT) | sigmask(SIGUSR1) |
sigmask(SIGUSR2) | sigmask(SIGCHLD) |
sigmask(SIGWINCH) | sigmask(SIGFPE);
StartupBlockSig = sigmask(SIGHUP) |
sigmask(SIGINT) | sigmask(SIGUSR1) |
sigmask(SIGUSR2) | sigmask(SIGCHLD) |
sigmask(SIGWINCH) | sigmask(SIGFPE);
#endif
}
/* Win32 signal handling is in backend/port/win32/signal.c */
#ifndef WIN32
/*
* Set up a signal handler
*/
pqsigfunc
pqsignal(int signo, pqsigfunc func)
{
#if !defined(HAVE_POSIX_SIGNALS)
return signal(signo, func);
#else
struct sigaction act,
oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (signo != SIGALRM)
act.sa_flags |= SA_RESTART;
#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;
#endif /* !HAVE_POSIX_SIGNALS */
}
#endif /* WIN32 */