Skip to content

Commit d8085b0

Browse files
macdicepull[bot]
authored andcommitted
Provide sigaction() for Windows.
Commit 9abb2bf 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 c94ae9d. Discussion: https://postgr.es/m/CA%2BhUKGKKKfcgx6jzok9AYenp2TNti_tfs8FMoJpL8%2B0Gsy%3D%3D_A%40mail.gmail.com
1 parent f86b81a commit d8085b0

File tree

5 files changed

+53
-79
lines changed

5 files changed

+53
-79
lines changed

src/backend/libpq/pqsignal.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,10 @@ pqinitmask(void)
110110
* postmaster ever unblocks signals.
111111
*
112112
* pqinitmask() must have been invoked previously.
113-
*
114-
* On Windows, this function is just an alias for pqsignal()
115-
* (and note that it's calling the code in src/backend/port/win32/signal.c,
116-
* not src/port/pqsignal.c). On that platform, the postmaster's signal
117-
* handlers still have to block signals for themselves.
118113
*/
119114
pqsigfunc
120115
pqsignal_pm(int signo, pqsigfunc func)
121116
{
122-
#ifndef WIN32
123117
struct sigaction act,
124118
oact;
125119

@@ -142,7 +136,4 @@ pqsignal_pm(int signo, pqsigfunc func)
142136
if (sigaction(signo, &act, &oact) < 0)
143137
return SIG_ERR;
144138
return oact.sa_handler;
145-
#else /* WIN32 */
146-
return pqsignal(signo, func);
147-
#endif
148139
}

src/backend/port/win32/signal.c

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ HANDLE pgwin32_initial_signal_pipe = INVALID_HANDLE_VALUE;
3434
static CRITICAL_SECTION pg_signal_crit_sec;
3535

3636
/* Note that array elements 0 are unused since they correspond to signal 0 */
37-
static pqsigfunc pg_signal_array[PG_SIGNAL_COUNT];
37+
static struct sigaction pg_signal_array[PG_SIGNAL_COUNT];
3838
static pqsigfunc pg_signal_defaults[PG_SIGNAL_COUNT];
3939

4040

@@ -85,7 +85,9 @@ pgwin32_signal_initialize(void)
8585

8686
for (i = 0; i < PG_SIGNAL_COUNT; i++)
8787
{
88-
pg_signal_array[i] = SIG_DFL;
88+
pg_signal_array[i].sa_handler = SIG_DFL;
89+
pg_signal_array[i].sa_mask = 0;
90+
pg_signal_array[i].sa_flags = 0;
8991
pg_signal_defaults[i] = SIG_IGN;
9092
}
9193
pg_signal_mask = 0;
@@ -131,15 +133,27 @@ pgwin32_dispatch_queued_signals(void)
131133
if (exec_mask & sigmask(i))
132134
{
133135
/* Execute this signal */
134-
pqsigfunc sig = pg_signal_array[i];
136+
struct sigaction *act = &pg_signal_array[i];
137+
pqsigfunc sig = act->sa_handler;
135138

136139
if (sig == SIG_DFL)
137140
sig = pg_signal_defaults[i];
138141
pg_signal_queue &= ~sigmask(i);
139142
if (sig != SIG_ERR && sig != SIG_IGN && sig != SIG_DFL)
140143
{
144+
sigset_t block_mask;
145+
sigset_t save_mask;
146+
141147
LeaveCriticalSection(&pg_signal_crit_sec);
148+
149+
block_mask = act->sa_mask;
150+
if ((act->sa_flags & SA_NODEFER) == 0)
151+
block_mask |= sigmask(i);
152+
153+
sigprocmask(SIG_BLOCK, &block_mask, &save_mask);
142154
sig(i);
155+
sigprocmask(SIG_SETMASK, &save_mask, NULL);
156+
143157
EnterCriticalSection(&pg_signal_crit_sec);
144158
break; /* Restart outer loop, in case signal mask or
145159
* queue has been modified inside signal
@@ -187,22 +201,25 @@ pqsigprocmask(int how, const sigset_t *set, sigset_t *oset)
187201
return 0;
188202
}
189203

190-
191204
/*
192205
* Unix-like signal handler installation
193206
*
194207
* Only called on main thread, no sync required
195208
*/
196-
pqsigfunc
197-
pqsignal(int signum, pqsigfunc handler)
209+
int
210+
pqsigaction(int signum, const struct sigaction *act,
211+
struct sigaction *oldact)
198212
{
199-
pqsigfunc prevfunc;
200-
201213
if (signum >= PG_SIGNAL_COUNT || signum < 0)
202-
return SIG_ERR;
203-
prevfunc = pg_signal_array[signum];
204-
pg_signal_array[signum] = handler;
205-
return prevfunc;
214+
{
215+
errno = EINVAL;
216+
return -1;
217+
}
218+
if (oldact)
219+
*oldact = pg_signal_array[signum];
220+
if (act)
221+
pg_signal_array[signum] = *act;
222+
return 0;
206223
}
207224

208225
/* Create the signal listener pipe for specified PID */

src/backend/postmaster/postmaster.c

Lines changed: 4 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -620,10 +620,10 @@ PostmasterMain(int argc, char *argv[])
620620
* is used by all child processes and client processes). That has a
621621
* couple of special behaviors:
622622
*
623-
* 1. Except on Windows, we tell sigaction() to block all signals for the
624-
* duration of the signal handler. This is faster than our old approach
625-
* of blocking/unblocking explicitly in the signal handler, and it should
626-
* also prevent excessive stack consumption if signals arrive quickly.
623+
* 1. We tell sigaction() to block all signals for the duration of the
624+
* signal handler. This is faster than our old approach of
625+
* blocking/unblocking explicitly in the signal handler, and it should also
626+
* prevent excessive stack consumption if signals arrive quickly.
627627
*
628628
* 2. We do not set the SA_RESTART flag. This is because signals will be
629629
* blocked at all times except when ServerLoop is waiting for something to
@@ -2726,14 +2726,6 @@ SIGHUP_handler(SIGNAL_ARGS)
27262726
{
27272727
int save_errno = errno;
27282728

2729-
/*
2730-
* We rely on the signal mechanism to have blocked all signals ... except
2731-
* on Windows, which lacks sigaction(), so we have to do it manually.
2732-
*/
2733-
#ifdef WIN32
2734-
PG_SETMASK(&BlockSig);
2735-
#endif
2736-
27372729
if (Shutdown <= SmartShutdown)
27382730
{
27392731
ereport(LOG,
@@ -2790,10 +2782,6 @@ SIGHUP_handler(SIGNAL_ARGS)
27902782
#endif
27912783
}
27922784

2793-
#ifdef WIN32
2794-
PG_SETMASK(&UnBlockSig);
2795-
#endif
2796-
27972785
errno = save_errno;
27982786
}
27992787

@@ -2806,14 +2794,6 @@ pmdie(SIGNAL_ARGS)
28062794
{
28072795
int save_errno = errno;
28082796

2809-
/*
2810-
* We rely on the signal mechanism to have blocked all signals ... except
2811-
* on Windows, which lacks sigaction(), so we have to do it manually.
2812-
*/
2813-
#ifdef WIN32
2814-
PG_SETMASK(&BlockSig);
2815-
#endif
2816-
28172797
ereport(DEBUG2,
28182798
(errmsg_internal("postmaster received signal %d",
28192799
postgres_signal_arg)));
@@ -2938,10 +2918,6 @@ pmdie(SIGNAL_ARGS)
29382918
break;
29392919
}
29402920

2941-
#ifdef WIN32
2942-
PG_SETMASK(&UnBlockSig);
2943-
#endif
2944-
29452921
errno = save_errno;
29462922
}
29472923

@@ -2955,14 +2931,6 @@ reaper(SIGNAL_ARGS)
29552931
int pid; /* process id of dead child process */
29562932
int exitstatus; /* its exit status */
29572933

2958-
/*
2959-
* We rely on the signal mechanism to have blocked all signals ... except
2960-
* on Windows, which lacks sigaction(), so we have to do it manually.
2961-
*/
2962-
#ifdef WIN32
2963-
PG_SETMASK(&BlockSig);
2964-
#endif
2965-
29662934
ereport(DEBUG4,
29672935
(errmsg_internal("reaping dead processes")));
29682936

@@ -3255,11 +3223,6 @@ reaper(SIGNAL_ARGS)
32553223
*/
32563224
PostmasterStateMachine();
32573225

3258-
/* Done with signal handler */
3259-
#ifdef WIN32
3260-
PG_SETMASK(&UnBlockSig);
3261-
#endif
3262-
32633226
errno = save_errno;
32643227
}
32653228

@@ -5106,14 +5069,6 @@ sigusr1_handler(SIGNAL_ARGS)
51065069
{
51075070
int save_errno = errno;
51085071

5109-
/*
5110-
* We rely on the signal mechanism to have blocked all signals ... except
5111-
* on Windows, which lacks sigaction(), so we have to do it manually.
5112-
*/
5113-
#ifdef WIN32
5114-
PG_SETMASK(&BlockSig);
5115-
#endif
5116-
51175072
/*
51185073
* RECOVERY_STARTED and BEGIN_HOT_STANDBY signals are ignored in
51195074
* unexpected states. If the startup process quickly starts up, completes
@@ -5254,10 +5209,6 @@ sigusr1_handler(SIGNAL_ARGS)
52545209
signal_child(StartupPID, SIGUSR2);
52555210
}
52565211

5257-
#ifdef WIN32
5258-
PG_SETMASK(&UnBlockSig);
5259-
#endif
5260-
52615212
errno = save_errno;
52625213
}
52635214

src/include/libpq/pqsignal.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,26 @@
2121
/* Emulate POSIX sigset_t APIs on Windows */
2222
typedef int sigset_t;
2323

24+
#define SA_RESTART 1
25+
#define SA_NODEFER 2
26+
27+
struct sigaction
28+
{
29+
void (*sa_handler) (int);
30+
/* sa_sigaction not yet implemented */
31+
sigset_t sa_mask;
32+
int sa_flags;
33+
};
34+
2435
extern int pqsigprocmask(int how, const sigset_t *set, sigset_t *oset);
36+
extern int pqsigaction(int signum, const struct sigaction *act,
37+
struct sigaction *oldact);
2538

2639
#define SIG_BLOCK 1
2740
#define SIG_UNBLOCK 2
2841
#define SIG_SETMASK 3
2942
#define sigprocmask(how, set, oset) pqsigprocmask((how), (set), (oset))
43+
#define sigaction(signum, act, oldact) pqsigaction((signum), (act), (oldact))
3044
#define sigemptyset(set) (*(set) = 0)
3145
#define sigfillset(set) (*(set) = ~0)
3246
#define sigaddset(set, signum) (*(set) |= (sigmask(signum)))

src/port/pqsignal.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929

3030
#include <signal.h>
3131

32-
#if !defined(WIN32) || defined(FRONTEND)
32+
#ifndef FRONTEND
33+
#include "libpq/pqsignal.h"
34+
#endif
3335

3436
/*
3537
* Set up a signal handler, with SA_RESTART, for signal "signo"
@@ -39,7 +41,7 @@
3941
pqsigfunc
4042
pqsignal(int signo, pqsigfunc func)
4143
{
42-
#ifndef WIN32
44+
#if !(defined(WIN32) && defined(FRONTEND))
4345
struct sigaction act,
4446
oact;
4547

@@ -53,9 +55,8 @@ pqsignal(int signo, pqsigfunc func)
5355
if (sigaction(signo, &act, &oact) < 0)
5456
return SIG_ERR;
5557
return oact.sa_handler;
56-
#else /* WIN32 */
58+
#else
59+
/* Forward to Windows native signal system. */
5760
return signal(signo, func);
5861
#endif
5962
}
60-
61-
#endif /* !defined(WIN32) || defined(FRONTEND) */

0 commit comments

Comments
 (0)