2013-03-17 17:06:42 +01:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* pqsignal.c
|
|
|
|
* reliable BSD-style signal(2) routine stolen from RWW who stole it
|
|
|
|
* from Stevens...
|
|
|
|
*
|
2024-01-04 02:49:05 +01:00
|
|
|
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
|
2013-03-17 17:06:42 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
|
|
|
* src/port/pqsignal.c
|
|
|
|
*
|
2023-11-24 21:41:33 +01:00
|
|
|
* This is the signal() implementation from "Advanced Programming in the UNIX
|
|
|
|
* Environment", with minor changes. It was originally a replacement needed
|
|
|
|
* for old SVR4 systems whose signal() behaved as if sa_flags = SA_RESETHAND |
|
|
|
|
* SA_NODEFER, also known as "unreliable" signals due to races when the
|
|
|
|
* handler was reset.
|
|
|
|
*
|
|
|
|
* By now, all known modern Unix systems have a "reliable" signal() call.
|
|
|
|
* We still don't want to use it though, because it remains
|
|
|
|
* implementation-defined by both C99 and POSIX whether the handler is reset
|
|
|
|
* or signals are blocked when the handler runs, and default restart behavior
|
|
|
|
* is also unspecified. Therefore we take POSIX's advice and call sigaction()
|
|
|
|
* so we can provide explicit sa_flags, but wrap it in this more convenient
|
|
|
|
* traditional interface style. It also provides a place to set any extra
|
|
|
|
* flags we want everywhere, such as SA_NOCLDSTOP.
|
2013-03-17 17:06:42 +01:00
|
|
|
*
|
2013-03-17 20:19:47 +01:00
|
|
|
* Windows, of course, is resolutely in a class by itself. In the backend,
|
2023-11-24 21:41:33 +01:00
|
|
|
* this relies on pqsigaction() in src/backend/port/win32/signal.c, which
|
|
|
|
* provides limited emulation of reliable signals.
|
|
|
|
*
|
2023-11-24 22:39:32 +01:00
|
|
|
* Frontend programs can use this version of pqsignal() to forward to the
|
|
|
|
* native Windows signal() call if they wish, but beware that Windows signals
|
|
|
|
* behave quite differently. Only the 6 signals required by C are supported.
|
|
|
|
* SIGINT handlers run in another thread instead of interrupting an existing
|
|
|
|
* thread, and the others don't interrupt system calls either, so SA_RESTART
|
|
|
|
* is moot. All except SIGFPE have SA_RESETHAND semantics, meaning the
|
|
|
|
* handler is reset to SIG_DFL each time it runs. The set of things you are
|
|
|
|
* allowed to do in a handler is also much more restricted than on Unix,
|
|
|
|
* according to the documentation.
|
Remove support for Unix systems without the POSIX signal APIs.
Remove configure's checks for HAVE_POSIX_SIGNALS, HAVE_SIGPROCMASK, and
HAVE_SIGSETJMP. These APIs are required by the Single Unix Spec v2
(POSIX 1997), which we generally consider to define our minimum required
set of Unix APIs. Moreover, no buildfarm member has reported not having
them since 2012 or before, which means that even if the code is still live
somewhere, it's untested --- and we've made plenty of signal-handling
changes of late. So just take these APIs as given and save the cycles for
configure probes for them.
However, we can't remove as much C code as I'd hoped, because the Windows
port evidently still uses the non-POSIX code paths for signal masking.
Since we're largely emulating these BSD-style APIs for Windows anyway, it
might be a good thing to switch over to POSIX-like notation and thereby
remove a few more #ifdefs. But I'm not in a position to code or test that.
In the meantime, we can at least make things a bit more transparent by
testing for WIN32 explicitly in these places.
2015-08-31 18:55:59 +02:00
|
|
|
*
|
2013-03-17 17:06:42 +01:00
|
|
|
* ------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "c.h"
|
|
|
|
|
|
|
|
#include <signal.h>
|
2024-02-14 21:52:14 +01:00
|
|
|
#ifndef FRONTEND
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
2013-03-17 17:06:42 +01:00
|
|
|
|
2022-11-09 01:05:16 +01:00
|
|
|
#ifndef FRONTEND
|
|
|
|
#include "libpq/pqsignal.h"
|
2024-02-14 21:52:14 +01:00
|
|
|
#include "miscadmin.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef PG_SIGNAL_COUNT /* Windows */
|
|
|
|
#define PG_NSIG (PG_SIGNAL_COUNT)
|
|
|
|
#elif defined(NSIG)
|
|
|
|
#define PG_NSIG (NSIG)
|
|
|
|
#else
|
|
|
|
#define PG_NSIG (64) /* XXX: wild guess */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Check a couple of common signals to make sure PG_NSIG is accurate. */
|
|
|
|
StaticAssertDecl(SIGUSR2 < PG_NSIG, "SIGUSR2 >= PG_NSIG");
|
|
|
|
StaticAssertDecl(SIGHUP < PG_NSIG, "SIGHUP >= PG_NSIG");
|
|
|
|
StaticAssertDecl(SIGTERM < PG_NSIG, "SIGTERM >= PG_NSIG");
|
|
|
|
StaticAssertDecl(SIGALRM < PG_NSIG, "SIGALRM >= PG_NSIG");
|
|
|
|
|
|
|
|
static volatile pqsigfunc pqsignal_handlers[PG_NSIG];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Except when called with SIG_IGN or SIG_DFL, pqsignal() sets up this function
|
|
|
|
* as the handler for all signals. This wrapper handler function checks that
|
|
|
|
* it is called within a process that the server knows about (i.e., any process
|
|
|
|
* that has called InitProcessGlobals(), such as a client backend), and not a
|
|
|
|
* child process forked by system(3), etc. This check ensures that such child
|
|
|
|
* processes do not modify shared memory, which is often detrimental. If the
|
|
|
|
* check succeeds, the function originally provided to pqsignal() is called.
|
|
|
|
* Otherwise, the default signal handler is installed and then called.
|
2024-02-14 23:34:18 +01:00
|
|
|
*
|
|
|
|
* This wrapper also handles restoring the value of errno.
|
2024-02-14 21:52:14 +01:00
|
|
|
*/
|
|
|
|
static void
|
|
|
|
wrapper_handler(SIGNAL_ARGS)
|
|
|
|
{
|
2024-02-14 23:34:18 +01:00
|
|
|
int save_errno = errno;
|
|
|
|
|
2024-02-14 21:52:14 +01:00
|
|
|
#ifndef FRONTEND
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We expect processes to set MyProcPid before calling pqsignal() or
|
|
|
|
* before accepting signals.
|
|
|
|
*/
|
|
|
|
Assert(MyProcPid);
|
|
|
|
Assert(MyProcPid != PostmasterPid || !IsUnderPostmaster);
|
|
|
|
|
|
|
|
if (unlikely(MyProcPid != (int) getpid()))
|
|
|
|
{
|
|
|
|
pqsignal(postgres_signal_arg, SIG_DFL);
|
|
|
|
raise(postgres_signal_arg);
|
|
|
|
return;
|
|
|
|
}
|
2022-11-09 01:05:16 +01:00
|
|
|
#endif
|
2013-03-17 17:06:42 +01:00
|
|
|
|
2024-02-14 21:52:14 +01:00
|
|
|
(*pqsignal_handlers[postgres_signal_arg]) (postgres_signal_arg);
|
2024-02-14 23:34:18 +01:00
|
|
|
|
|
|
|
errno = save_errno;
|
2024-02-14 21:52:14 +01:00
|
|
|
}
|
|
|
|
|
2013-03-17 17:06:42 +01:00
|
|
|
/*
|
Run the postmaster's signal handlers without SA_RESTART.
The postmaster keeps signals blocked everywhere except while waiting
for something to happen in ServerLoop(). The code expects that the
select(2) will be cancelled with EINTR if an interrupt occurs; without
that, followup actions that should be performed by ServerLoop() itself
will be delayed. However, some platforms interpret the SA_RESTART
signal flag as meaning that they should restart rather than cancel
the select(2). Worse yet, some of them restart it with the original
timeout delay, meaning that a steady stream of signal interrupts can
prevent ServerLoop() from iterating at all if there are no incoming
connection requests.
Observable symptoms of this, on an affected platform such as HPUX 10,
include extremely slow parallel query startup (possibly as much as
30 seconds) and failure to update timestamps on the postmaster's sockets
and lockfiles when no new connections arrive for a long time.
We can fix this by running the postmaster's signal handlers without
SA_RESTART. That would be quite a scary change if the range of code
where signals are accepted weren't so tiny, but as it is, it seems
safe enough. (Note that postmaster children do, and must, reset all
the handlers before unblocking signals; so this change should not
affect any child process.)
There is talk of rewriting the postmaster to use a WaitEventSet and
not do signal response work in signal handlers, at which point it might
be appropriate to revert this patch. But that's not happening before
v11 at the earliest.
Back-patch to 9.6. The problem exists much further back, but the
worst symptom arises only in connection with parallel query, so it
does not seem worth taking any portability risks in older branches.
Discussion: https://postgr.es/m/9205.1492833041@sss.pgh.pa.us
2017-04-24 19:00:23 +02:00
|
|
|
* Set up a signal handler, with SA_RESTART, for signal "signo"
|
2013-03-17 17:06:42 +01:00
|
|
|
*
|
2013-03-17 20:19:47 +01:00
|
|
|
* Returns the previous handler.
|
2024-02-14 21:52:14 +01:00
|
|
|
*
|
|
|
|
* NB: If called within a signal handler, race conditions may lead to bogus
|
|
|
|
* return values. You should either avoid calling this within signal handlers
|
|
|
|
* or ignore the return value.
|
|
|
|
*
|
|
|
|
* XXX: Since no in-tree callers use the return value, and there is little
|
|
|
|
* reason to do so, it would be nice if we could convert this to a void
|
|
|
|
* function instead of providing potentially-bogus return values.
|
|
|
|
* Unfortunately, that requires modifying the pqsignal() in legacy-pqsignal.c,
|
|
|
|
* which in turn requires an SONAME bump, which is probably not worth it.
|
2013-03-17 17:06:42 +01:00
|
|
|
*/
|
|
|
|
pqsigfunc
|
|
|
|
pqsignal(int signo, pqsigfunc func)
|
|
|
|
{
|
2024-02-14 21:52:14 +01:00
|
|
|
pqsigfunc orig_func = pqsignal_handlers[signo]; /* assumed atomic */
|
2022-11-09 01:05:16 +01:00
|
|
|
#if !(defined(WIN32) && defined(FRONTEND))
|
2013-03-17 17:06:42 +01:00
|
|
|
struct sigaction act,
|
|
|
|
oact;
|
2024-02-14 21:52:14 +01:00
|
|
|
#else
|
|
|
|
pqsigfunc ret;
|
|
|
|
#endif
|
2013-03-17 17:06:42 +01:00
|
|
|
|
2024-02-14 21:52:14 +01:00
|
|
|
Assert(signo < PG_NSIG);
|
|
|
|
|
|
|
|
if (func != SIG_IGN && func != SIG_DFL)
|
|
|
|
{
|
|
|
|
pqsignal_handlers[signo] = func; /* assumed atomic */
|
|
|
|
func = wrapper_handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if !(defined(WIN32) && defined(FRONTEND))
|
2013-03-17 17:06:42 +01:00
|
|
|
act.sa_handler = func;
|
|
|
|
sigemptyset(&act.sa_mask);
|
2013-06-15 21:39:51 +02:00
|
|
|
act.sa_flags = SA_RESTART;
|
2013-03-17 17:06:42 +01:00
|
|
|
#ifdef SA_NOCLDSTOP
|
|
|
|
if (signo == SIGCHLD)
|
|
|
|
act.sa_flags |= SA_NOCLDSTOP;
|
|
|
|
#endif
|
|
|
|
if (sigaction(signo, &act, &oact) < 0)
|
|
|
|
return SIG_ERR;
|
2024-02-14 21:52:14 +01:00
|
|
|
else if (oact.sa_handler == wrapper_handler)
|
|
|
|
return orig_func;
|
|
|
|
else
|
|
|
|
return oact.sa_handler;
|
2022-11-09 01:05:16 +01:00
|
|
|
#else
|
|
|
|
/* Forward to Windows native signal system. */
|
2024-02-14 21:52:14 +01:00
|
|
|
if ((ret = signal(signo, func)) == wrapper_handler)
|
|
|
|
return orig_func;
|
|
|
|
else
|
|
|
|
return ret;
|
Remove support for Unix systems without the POSIX signal APIs.
Remove configure's checks for HAVE_POSIX_SIGNALS, HAVE_SIGPROCMASK, and
HAVE_SIGSETJMP. These APIs are required by the Single Unix Spec v2
(POSIX 1997), which we generally consider to define our minimum required
set of Unix APIs. Moreover, no buildfarm member has reported not having
them since 2012 or before, which means that even if the code is still live
somewhere, it's untested --- and we've made plenty of signal-handling
changes of late. So just take these APIs as given and save the cycles for
configure probes for them.
However, we can't remove as much C code as I'd hoped, because the Windows
port evidently still uses the non-POSIX code paths for signal masking.
Since we're largely emulating these BSD-style APIs for Windows anyway, it
might be a good thing to switch over to POSIX-like notation and thereby
remove a few more #ifdefs. But I'm not in a position to code or test that.
In the meantime, we can at least make things a bit more transparent by
testing for WIN32 explicitly in these places.
2015-08-31 18:55:59 +02:00
|
|
|
#endif
|
2013-03-17 17:06:42 +01:00
|
|
|
}
|