mirror of
https://github.com/postgres/postgres.git
synced 2025-06-08 00:01:54 -04:00
Provide sigaction() for Windows.
Commit 9abb2bfc left behind code to block signals inside signal handlers on Windows, because our signal porting layer didn't have sigaction(). Provide a minimal implementation that is capable of blocking signals, to get rid of platform differences. See also related commit c94ae9d8. Discussion: https://postgr.es/m/CA%2BhUKGKKKfcgx6jzok9AYenp2TNti_tfs8FMoJpL8%2B0Gsy%3D%3D_A%40mail.gmail.com
This commit is contained in:
parent
6bbd8b7385
commit
b28ac1d24d
@ -110,16 +110,10 @@ pqinitmask(void)
|
|||||||
* postmaster ever unblocks signals.
|
* postmaster ever unblocks signals.
|
||||||
*
|
*
|
||||||
* pqinitmask() must have been invoked previously.
|
* 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
|
pqsigfunc
|
||||||
pqsignal_pm(int signo, pqsigfunc func)
|
pqsignal_pm(int signo, pqsigfunc func)
|
||||||
{
|
{
|
||||||
#ifndef WIN32
|
|
||||||
struct sigaction act,
|
struct sigaction act,
|
||||||
oact;
|
oact;
|
||||||
|
|
||||||
@ -142,7 +136,4 @@ pqsignal_pm(int signo, pqsigfunc func)
|
|||||||
if (sigaction(signo, &act, &oact) < 0)
|
if (sigaction(signo, &act, &oact) < 0)
|
||||||
return SIG_ERR;
|
return SIG_ERR;
|
||||||
return oact.sa_handler;
|
return oact.sa_handler;
|
||||||
#else /* WIN32 */
|
|
||||||
return pqsignal(signo, func);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ HANDLE pgwin32_initial_signal_pipe = INVALID_HANDLE_VALUE;
|
|||||||
static CRITICAL_SECTION pg_signal_crit_sec;
|
static CRITICAL_SECTION pg_signal_crit_sec;
|
||||||
|
|
||||||
/* Note that array elements 0 are unused since they correspond to signal 0 */
|
/* Note that array elements 0 are unused since they correspond to signal 0 */
|
||||||
static pqsigfunc pg_signal_array[PG_SIGNAL_COUNT];
|
static struct sigaction pg_signal_array[PG_SIGNAL_COUNT];
|
||||||
static pqsigfunc pg_signal_defaults[PG_SIGNAL_COUNT];
|
static pqsigfunc pg_signal_defaults[PG_SIGNAL_COUNT];
|
||||||
|
|
||||||
|
|
||||||
@ -85,7 +85,9 @@ pgwin32_signal_initialize(void)
|
|||||||
|
|
||||||
for (i = 0; i < PG_SIGNAL_COUNT; i++)
|
for (i = 0; i < PG_SIGNAL_COUNT; i++)
|
||||||
{
|
{
|
||||||
pg_signal_array[i] = SIG_DFL;
|
pg_signal_array[i].sa_handler = SIG_DFL;
|
||||||
|
pg_signal_array[i].sa_mask = 0;
|
||||||
|
pg_signal_array[i].sa_flags = 0;
|
||||||
pg_signal_defaults[i] = SIG_IGN;
|
pg_signal_defaults[i] = SIG_IGN;
|
||||||
}
|
}
|
||||||
pg_signal_mask = 0;
|
pg_signal_mask = 0;
|
||||||
@ -131,15 +133,27 @@ pgwin32_dispatch_queued_signals(void)
|
|||||||
if (exec_mask & sigmask(i))
|
if (exec_mask & sigmask(i))
|
||||||
{
|
{
|
||||||
/* Execute this signal */
|
/* Execute this signal */
|
||||||
pqsigfunc sig = pg_signal_array[i];
|
struct sigaction *act = &pg_signal_array[i];
|
||||||
|
pqsigfunc sig = act->sa_handler;
|
||||||
|
|
||||||
if (sig == SIG_DFL)
|
if (sig == SIG_DFL)
|
||||||
sig = pg_signal_defaults[i];
|
sig = pg_signal_defaults[i];
|
||||||
pg_signal_queue &= ~sigmask(i);
|
pg_signal_queue &= ~sigmask(i);
|
||||||
if (sig != SIG_ERR && sig != SIG_IGN && sig != SIG_DFL)
|
if (sig != SIG_ERR && sig != SIG_IGN && sig != SIG_DFL)
|
||||||
{
|
{
|
||||||
|
sigset_t block_mask;
|
||||||
|
sigset_t save_mask;
|
||||||
|
|
||||||
LeaveCriticalSection(&pg_signal_crit_sec);
|
LeaveCriticalSection(&pg_signal_crit_sec);
|
||||||
|
|
||||||
|
block_mask = act->sa_mask;
|
||||||
|
if ((act->sa_flags & SA_NODEFER) == 0)
|
||||||
|
block_mask |= sigmask(i);
|
||||||
|
|
||||||
|
sigprocmask(SIG_BLOCK, &block_mask, &save_mask);
|
||||||
sig(i);
|
sig(i);
|
||||||
|
sigprocmask(SIG_SETMASK, &save_mask, NULL);
|
||||||
|
|
||||||
EnterCriticalSection(&pg_signal_crit_sec);
|
EnterCriticalSection(&pg_signal_crit_sec);
|
||||||
break; /* Restart outer loop, in case signal mask or
|
break; /* Restart outer loop, in case signal mask or
|
||||||
* queue has been modified inside signal
|
* queue has been modified inside signal
|
||||||
@ -187,22 +201,25 @@ pqsigprocmask(int how, const sigset_t *set, sigset_t *oset)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unix-like signal handler installation
|
* Unix-like signal handler installation
|
||||||
*
|
*
|
||||||
* Only called on main thread, no sync required
|
* Only called on main thread, no sync required
|
||||||
*/
|
*/
|
||||||
pqsigfunc
|
int
|
||||||
pqsignal(int signum, pqsigfunc handler)
|
pqsigaction(int signum, const struct sigaction *act,
|
||||||
|
struct sigaction *oldact)
|
||||||
{
|
{
|
||||||
pqsigfunc prevfunc;
|
|
||||||
|
|
||||||
if (signum >= PG_SIGNAL_COUNT || signum < 0)
|
if (signum >= PG_SIGNAL_COUNT || signum < 0)
|
||||||
return SIG_ERR;
|
{
|
||||||
prevfunc = pg_signal_array[signum];
|
errno = EINVAL;
|
||||||
pg_signal_array[signum] = handler;
|
return -1;
|
||||||
return prevfunc;
|
}
|
||||||
|
if (oldact)
|
||||||
|
*oldact = pg_signal_array[signum];
|
||||||
|
if (act)
|
||||||
|
pg_signal_array[signum] = *act;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the signal listener pipe for specified PID */
|
/* Create the signal listener pipe for specified PID */
|
||||||
|
@ -620,10 +620,10 @@ PostmasterMain(int argc, char *argv[])
|
|||||||
* is used by all child processes and client processes). That has a
|
* is used by all child processes and client processes). That has a
|
||||||
* couple of special behaviors:
|
* couple of special behaviors:
|
||||||
*
|
*
|
||||||
* 1. Except on Windows, we tell sigaction() to block all signals for the
|
* 1. We tell sigaction() to block all signals for the duration of the
|
||||||
* duration of the signal handler. This is faster than our old approach
|
* signal handler. This is faster than our old approach of
|
||||||
* of blocking/unblocking explicitly in the signal handler, and it should
|
* blocking/unblocking explicitly in the signal handler, and it should also
|
||||||
* also prevent excessive stack consumption if signals arrive quickly.
|
* prevent excessive stack consumption if signals arrive quickly.
|
||||||
*
|
*
|
||||||
* 2. We do not set the SA_RESTART flag. This is because signals will be
|
* 2. We do not set the SA_RESTART flag. This is because signals will be
|
||||||
* blocked at all times except when ServerLoop is waiting for something to
|
* blocked at all times except when ServerLoop is waiting for something to
|
||||||
@ -2726,14 +2726,6 @@ SIGHUP_handler(SIGNAL_ARGS)
|
|||||||
{
|
{
|
||||||
int save_errno = errno;
|
int save_errno = errno;
|
||||||
|
|
||||||
/*
|
|
||||||
* We rely on the signal mechanism to have blocked all signals ... except
|
|
||||||
* on Windows, which lacks sigaction(), so we have to do it manually.
|
|
||||||
*/
|
|
||||||
#ifdef WIN32
|
|
||||||
PG_SETMASK(&BlockSig);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (Shutdown <= SmartShutdown)
|
if (Shutdown <= SmartShutdown)
|
||||||
{
|
{
|
||||||
ereport(LOG,
|
ereport(LOG,
|
||||||
@ -2790,10 +2782,6 @@ SIGHUP_handler(SIGNAL_ARGS)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
PG_SETMASK(&UnBlockSig);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
errno = save_errno;
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2806,14 +2794,6 @@ pmdie(SIGNAL_ARGS)
|
|||||||
{
|
{
|
||||||
int save_errno = errno;
|
int save_errno = errno;
|
||||||
|
|
||||||
/*
|
|
||||||
* We rely on the signal mechanism to have blocked all signals ... except
|
|
||||||
* on Windows, which lacks sigaction(), so we have to do it manually.
|
|
||||||
*/
|
|
||||||
#ifdef WIN32
|
|
||||||
PG_SETMASK(&BlockSig);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ereport(DEBUG2,
|
ereport(DEBUG2,
|
||||||
(errmsg_internal("postmaster received signal %d",
|
(errmsg_internal("postmaster received signal %d",
|
||||||
postgres_signal_arg)));
|
postgres_signal_arg)));
|
||||||
@ -2938,10 +2918,6 @@ pmdie(SIGNAL_ARGS)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
PG_SETMASK(&UnBlockSig);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
errno = save_errno;
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2955,14 +2931,6 @@ reaper(SIGNAL_ARGS)
|
|||||||
int pid; /* process id of dead child process */
|
int pid; /* process id of dead child process */
|
||||||
int exitstatus; /* its exit status */
|
int exitstatus; /* its exit status */
|
||||||
|
|
||||||
/*
|
|
||||||
* We rely on the signal mechanism to have blocked all signals ... except
|
|
||||||
* on Windows, which lacks sigaction(), so we have to do it manually.
|
|
||||||
*/
|
|
||||||
#ifdef WIN32
|
|
||||||
PG_SETMASK(&BlockSig);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ereport(DEBUG4,
|
ereport(DEBUG4,
|
||||||
(errmsg_internal("reaping dead processes")));
|
(errmsg_internal("reaping dead processes")));
|
||||||
|
|
||||||
@ -3255,11 +3223,6 @@ reaper(SIGNAL_ARGS)
|
|||||||
*/
|
*/
|
||||||
PostmasterStateMachine();
|
PostmasterStateMachine();
|
||||||
|
|
||||||
/* Done with signal handler */
|
|
||||||
#ifdef WIN32
|
|
||||||
PG_SETMASK(&UnBlockSig);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
errno = save_errno;
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5106,14 +5069,6 @@ sigusr1_handler(SIGNAL_ARGS)
|
|||||||
{
|
{
|
||||||
int save_errno = errno;
|
int save_errno = errno;
|
||||||
|
|
||||||
/*
|
|
||||||
* We rely on the signal mechanism to have blocked all signals ... except
|
|
||||||
* on Windows, which lacks sigaction(), so we have to do it manually.
|
|
||||||
*/
|
|
||||||
#ifdef WIN32
|
|
||||||
PG_SETMASK(&BlockSig);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RECOVERY_STARTED and BEGIN_HOT_STANDBY signals are ignored in
|
* RECOVERY_STARTED and BEGIN_HOT_STANDBY signals are ignored in
|
||||||
* unexpected states. If the startup process quickly starts up, completes
|
* unexpected states. If the startup process quickly starts up, completes
|
||||||
@ -5254,10 +5209,6 @@ sigusr1_handler(SIGNAL_ARGS)
|
|||||||
signal_child(StartupPID, SIGUSR2);
|
signal_child(StartupPID, SIGUSR2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
PG_SETMASK(&UnBlockSig);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
errno = save_errno;
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,12 +21,26 @@
|
|||||||
/* Emulate POSIX sigset_t APIs on Windows */
|
/* Emulate POSIX sigset_t APIs on Windows */
|
||||||
typedef int sigset_t;
|
typedef int sigset_t;
|
||||||
|
|
||||||
|
#define SA_RESTART 1
|
||||||
|
#define SA_NODEFER 2
|
||||||
|
|
||||||
|
struct sigaction
|
||||||
|
{
|
||||||
|
void (*sa_handler) (int);
|
||||||
|
/* sa_sigaction not yet implemented */
|
||||||
|
sigset_t sa_mask;
|
||||||
|
int sa_flags;
|
||||||
|
};
|
||||||
|
|
||||||
extern int pqsigprocmask(int how, const sigset_t *set, sigset_t *oset);
|
extern int pqsigprocmask(int how, const sigset_t *set, sigset_t *oset);
|
||||||
|
extern int pqsigaction(int signum, const struct sigaction *act,
|
||||||
|
struct sigaction *oldact);
|
||||||
|
|
||||||
#define SIG_BLOCK 1
|
#define SIG_BLOCK 1
|
||||||
#define SIG_UNBLOCK 2
|
#define SIG_UNBLOCK 2
|
||||||
#define SIG_SETMASK 3
|
#define SIG_SETMASK 3
|
||||||
#define sigprocmask(how, set, oset) pqsigprocmask((how), (set), (oset))
|
#define sigprocmask(how, set, oset) pqsigprocmask((how), (set), (oset))
|
||||||
|
#define sigaction(signum, act, oldact) pqsigaction((signum), (act), (oldact))
|
||||||
#define sigemptyset(set) (*(set) = 0)
|
#define sigemptyset(set) (*(set) = 0)
|
||||||
#define sigfillset(set) (*(set) = ~0)
|
#define sigfillset(set) (*(set) = ~0)
|
||||||
#define sigaddset(set, signum) (*(set) |= (sigmask(signum)))
|
#define sigaddset(set, signum) (*(set) |= (sigmask(signum)))
|
||||||
|
@ -29,7 +29,9 @@
|
|||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#if !defined(WIN32) || defined(FRONTEND)
|
#ifndef FRONTEND
|
||||||
|
#include "libpq/pqsignal.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up a signal handler, with SA_RESTART, for signal "signo"
|
* Set up a signal handler, with SA_RESTART, for signal "signo"
|
||||||
@ -39,7 +41,7 @@
|
|||||||
pqsigfunc
|
pqsigfunc
|
||||||
pqsignal(int signo, pqsigfunc func)
|
pqsignal(int signo, pqsigfunc func)
|
||||||
{
|
{
|
||||||
#ifndef WIN32
|
#if !(defined(WIN32) && defined(FRONTEND))
|
||||||
struct sigaction act,
|
struct sigaction act,
|
||||||
oact;
|
oact;
|
||||||
|
|
||||||
@ -53,9 +55,8 @@ pqsignal(int signo, pqsigfunc func)
|
|||||||
if (sigaction(signo, &act, &oact) < 0)
|
if (sigaction(signo, &act, &oact) < 0)
|
||||||
return SIG_ERR;
|
return SIG_ERR;
|
||||||
return oact.sa_handler;
|
return oact.sa_handler;
|
||||||
#else /* WIN32 */
|
#else
|
||||||
|
/* Forward to Windows native signal system. */
|
||||||
return signal(signo, func);
|
return signal(signo, func);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !defined(WIN32) || defined(FRONTEND) */
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user