PostgreSQL Source Code  git master
pmsignal.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * pmsignal.c
4  * routines for signaling between the postmaster and its child processes
5  *
6  *
7  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  * IDENTIFICATION
11  * src/backend/storage/ipc/pmsignal.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include <signal.h>
18 #include <unistd.h>
19 
20 #ifdef HAVE_SYS_PRCTL_H
21 #include <sys/prctl.h>
22 #endif
23 
24 #include "miscadmin.h"
25 #include "postmaster/postmaster.h"
26 #include "replication/walsender.h"
27 #include "storage/pmsignal.h"
28 #include "storage/shmem.h"
29 
30 
31 /*
32  * The postmaster is signaled by its children by sending SIGUSR1. The
33  * specific reason is communicated via flags in shared memory. We keep
34  * a boolean flag for each possible "reason", so that different reasons
35  * can be signaled by different backends at the same time. (However,
36  * if the same reason is signaled more than once simultaneously, the
37  * postmaster will observe it only once.)
38  *
39  * The flags are actually declared as "volatile sig_atomic_t" for maximum
40  * portability. This should ensure that loads and stores of the flag
41  * values are atomic, allowing us to dispense with any explicit locking.
42  *
43  * In addition to the per-reason flags, we store a set of per-child-process
44  * flags that are currently used only for detecting whether a backend has
45  * exited without performing proper shutdown. The per-child-process flags
46  * have three possible states: UNUSED, ASSIGNED, ACTIVE. An UNUSED slot is
47  * available for assignment. An ASSIGNED slot is associated with a postmaster
48  * child process, but either the process has not touched shared memory yet,
49  * or it has successfully cleaned up after itself. A ACTIVE slot means the
50  * process is actively using shared memory. The slots are assigned to
51  * child processes at random, and postmaster.c is responsible for tracking
52  * which one goes with which PID.
53  *
54  * Actually there is a fourth state, WALSENDER. This is just like ACTIVE,
55  * but carries the extra information that the child is a WAL sender.
56  * WAL senders too start in ACTIVE state, but switch to WALSENDER once they
57  * start streaming the WAL (and they never go back to ACTIVE after that).
58  *
59  * We also have a shared-memory field that is used for communication in
60  * the opposite direction, from postmaster to children: it tells why the
61  * postmaster has broadcasted SIGQUIT signals, if indeed it has done so.
62  */
63 
64 #define PM_CHILD_UNUSED 0 /* these values must fit in sig_atomic_t */
65 #define PM_CHILD_ASSIGNED 1
66 #define PM_CHILD_ACTIVE 2
67 #define PM_CHILD_WALSENDER 3
68 
69 /* "typedef struct PMSignalData PMSignalData" appears in pmsignal.h */
71 {
72  /* per-reason flags for signaling the postmaster */
74  /* global flags for signals from postmaster to children */
75  QuitSignalReason sigquit_reason; /* why SIGQUIT was sent */
76  /* per-child-process flags */
77  int num_child_flags; /* # of entries in PMChildFlags[] */
78  int next_child_flag; /* next slot to try to assign */
80 };
81 
83 
84 /*
85  * Signal handler to be notified if postmaster dies.
86  */
87 #ifdef USE_POSTMASTER_DEATH_SIGNAL
88 volatile sig_atomic_t postmaster_possibly_dead = false;
89 
90 static void
91 postmaster_death_handler(int signo)
92 {
93  postmaster_possibly_dead = true;
94 }
95 
96 /*
97  * The available signals depend on the OS. SIGUSR1 and SIGUSR2 are already
98  * used for other things, so choose another one.
99  *
100  * Currently, we assume that we can always find a signal to use. That
101  * seems like a reasonable assumption for all platforms that are modern
102  * enough to have a parent-death signaling mechanism.
103  */
104 #if defined(SIGINFO)
105 #define POSTMASTER_DEATH_SIGNAL SIGINFO
106 #elif defined(SIGPWR)
107 #define POSTMASTER_DEATH_SIGNAL SIGPWR
108 #else
109 #error "cannot find a signal to use for postmaster death"
110 #endif
111 
112 #endif /* USE_POSTMASTER_DEATH_SIGNAL */
113 
114 /*
115  * PMSignalShmemSize
116  * Compute space needed for pmsignal.c's shared memory
117  */
118 Size
120 {
121  Size size;
122 
125  sizeof(sig_atomic_t)));
126 
127  return size;
128 }
129 
130 /*
131  * PMSignalShmemInit - initialize during shared-memory creation
132  */
133 void
135 {
136  bool found;
137 
139  ShmemInitStruct("PMSignalState", PMSignalShmemSize(), &found);
140 
141  if (!found)
142  {
143  /* initialize all flags to zeroes */
146  }
147 }
148 
149 /*
150  * SendPostmasterSignal - signal the postmaster from a child process
151  */
152 void
154 {
155  /* If called in a standalone backend, do nothing */
156  if (!IsUnderPostmaster)
157  return;
158  /* Atomically set the proper flag */
159  PMSignalState->PMSignalFlags[reason] = true;
160  /* Send signal to postmaster */
162 }
163 
164 /*
165  * CheckPostmasterSignal - check to see if a particular reason has been
166  * signaled, and clear the signal flag. Should be called by postmaster
167  * after receiving SIGUSR1.
168  */
169 bool
171 {
172  /* Careful here --- don't clear flag if we haven't seen it set */
173  if (PMSignalState->PMSignalFlags[reason])
174  {
175  PMSignalState->PMSignalFlags[reason] = false;
176  return true;
177  }
178  return false;
179 }
180 
181 /*
182  * SetQuitSignalReason - broadcast the reason for a system shutdown.
183  * Should be called by postmaster before sending SIGQUIT to children.
184  *
185  * Note: in a crash-and-restart scenario, the "reason" field gets cleared
186  * as a part of rebuilding shared memory; the postmaster need not do it
187  * explicitly.
188  */
189 void
191 {
192  PMSignalState->sigquit_reason = reason;
193 }
194 
195 /*
196  * GetQuitSignalReason - obtain the reason for a system shutdown.
197  * Called by child processes when they receive SIGQUIT.
198  * If the postmaster hasn't actually sent SIGQUIT, will return PMQUIT_NOT_SENT.
199  */
202 {
203  /* This is called in signal handlers, so be extra paranoid. */
204  if (!IsUnderPostmaster || PMSignalState == NULL)
205  return PMQUIT_NOT_SENT;
207 }
208 
209 
210 /*
211  * AssignPostmasterChildSlot - select an unused slot for a new postmaster
212  * child process, and set its state to ASSIGNED. Returns a slot number
213  * (one to N).
214  *
215  * Only the postmaster is allowed to execute this routine, so we need no
216  * special locking.
217  */
218 int
220 {
221  int slot = PMSignalState->next_child_flag;
222  int n;
223 
224  /*
225  * Scan for a free slot. We track the last slot assigned so as not to
226  * waste time repeatedly rescanning low-numbered slots.
227  */
228  for (n = PMSignalState->num_child_flags; n > 0; n--)
229  {
230  if (--slot < 0)
231  slot = PMSignalState->num_child_flags - 1;
233  {
236  return slot + 1;
237  }
238  }
239 
240  /* Out of slots ... should never happen, else postmaster.c messed up */
241  elog(FATAL, "no free slots in PMChildFlags array");
242  return 0; /* keep compiler quiet */
243 }
244 
245 /*
246  * ReleasePostmasterChildSlot - release a slot after death of a postmaster
247  * child process. This must be called in the postmaster process.
248  *
249  * Returns true if the slot had been in ASSIGNED state (the expected case),
250  * false otherwise (implying that the child failed to clean itself up).
251  */
252 bool
254 {
255  bool result;
256 
257  Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
258  slot--;
259 
260  /*
261  * Note: the slot state might already be unused, because the logic in
262  * postmaster.c is such that this might get called twice when a child
263  * crashes. So we don't try to Assert anything about the state.
264  */
265  result = (PMSignalState->PMChildFlags[slot] == PM_CHILD_ASSIGNED);
267  return result;
268 }
269 
270 /*
271  * IsPostmasterChildWalSender - check if given slot is in use by a
272  * walsender process.
273  */
274 bool
276 {
277  Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
278  slot--;
279 
281  return true;
282  else
283  return false;
284 }
285 
286 /*
287  * MarkPostmasterChildActive - mark a postmaster child as about to begin
288  * actively using shared memory. This is called in the child process.
289  */
290 void
292 {
293  int slot = MyPMChildSlot;
294 
295  Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
296  slot--;
299 }
300 
301 /*
302  * MarkPostmasterChildWalSender - mark a postmaster child as a WAL sender
303  * process. This is called in the child process, sometime after marking the
304  * child as active.
305  */
306 void
308 {
309  int slot = MyPMChildSlot;
310 
312 
313  Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
314  slot--;
317 }
318 
319 /*
320  * MarkPostmasterChildInactive - mark a postmaster child as done using
321  * shared memory. This is called in the child process.
322  */
323 void
325 {
326  int slot = MyPMChildSlot;
327 
328  Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
329  slot--;
333 }
334 
335 
336 /*
337  * PostmasterIsAliveInternal - check whether postmaster process is still alive
338  *
339  * This is the slow path of PostmasterIsAlive(), where the caller has already
340  * checked 'postmaster_possibly_dead'. (On platforms that don't support
341  * a signal for parent death, PostmasterIsAlive() is just an alias for this.)
342  */
343 bool
345 {
346 #ifdef USE_POSTMASTER_DEATH_SIGNAL
347  /*
348  * Reset the flag before checking, so that we don't miss a signal if
349  * postmaster dies right after the check. If postmaster was indeed dead,
350  * we'll re-arm it before returning to caller.
351  */
352  postmaster_possibly_dead = false;
353 #endif
354 
355 #ifndef WIN32
356  {
357  char c;
358  ssize_t rc;
359 
361 
362  /*
363  * In the usual case, the postmaster is still alive, and there is no
364  * data in the pipe.
365  */
366  if (rc < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))
367  return true;
368  else
369  {
370  /*
371  * Postmaster is dead, or something went wrong with the read()
372  * call.
373  */
374 
375 #ifdef USE_POSTMASTER_DEATH_SIGNAL
376  postmaster_possibly_dead = true;
377 #endif
378 
379  if (rc < 0)
380  elog(FATAL, "read on postmaster death monitoring pipe failed: %m");
381  else if (rc > 0)
382  elog(FATAL, "unexpected data in postmaster death monitoring pipe");
383 
384  return false;
385  }
386  }
387 
388 #else /* WIN32 */
389  if (WaitForSingleObject(PostmasterHandle, 0) == WAIT_TIMEOUT)
390  return true;
391  else
392  {
393 #ifdef USE_POSTMASTER_DEATH_SIGNAL
394  postmaster_possibly_dead = true;
395 #endif
396  return false;
397  }
398 #endif /* WIN32 */
399 }
400 
401 /*
402  * PostmasterDeathSignalInit - request signal on postmaster death if possible
403  */
404 void
406 {
407 #ifdef USE_POSTMASTER_DEATH_SIGNAL
408  int signum = POSTMASTER_DEATH_SIGNAL;
409 
410  /* Register our signal handler. */
411  pqsignal(signum, postmaster_death_handler);
412 
413  /* Request a signal on parent exit. */
414 #if defined(PR_SET_PDEATHSIG)
415  if (prctl(PR_SET_PDEATHSIG, signum) < 0)
416  elog(ERROR, "could not request parent death signal: %m");
417 #elif defined(PROC_PDEATHSIG_CTL)
418  if (procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum) < 0)
419  elog(ERROR, "could not request parent death signal: %m");
420 #else
421 #error "USE_POSTMASTER_DEATH_SIGNAL set, but there is no mechanism to request the signal"
422 #endif
423 
424  /*
425  * Just in case the parent was gone already and we missed it, we'd better
426  * check the slow way on the first call.
427  */
428  postmaster_possibly_dead = true;
429 #endif /* USE_POSTMASTER_DEATH_SIGNAL */
430 }
int next_child_flag
Definition: pmsignal.c:78
Size PMSignalShmemSize(void)
Definition: pmsignal.c:119
bool CheckPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:170
#define EAGAIN
Definition: win32_port.h:341
#define SIGUSR1
Definition: win32_port.h:171
NON_EXEC_STATIC volatile PMSignalData * PMSignalState
Definition: pmsignal.c:82
void MarkPostmasterChildWalSender(void)
Definition: pmsignal.c:307
#define PM_CHILD_ACTIVE
Definition: pmsignal.c:66
QuitSignalReason GetQuitSignalReason(void)
Definition: pmsignal.c:201
#define FLEXIBLE_ARRAY_MEMBER
Definition: c.h:350
#define PM_CHILD_ASSIGNED
Definition: pmsignal.c:65
#define MemSet(start, val, len)
Definition: c.h:1008
void MarkPostmasterChildInactive(void)
Definition: pmsignal.c:324
#define kill(pid, sig)
Definition: win32_port.h:454
bool ReleasePostmasterChildSlot(int slot)
Definition: pmsignal.c:253
QuitSignalReason
Definition: pmsignal.h:50
QuitSignalReason sigquit_reason
Definition: pmsignal.c:75
int AssignPostmasterChildSlot(void)
Definition: pmsignal.c:219
bool am_walsender
Definition: walsender.c:115
int num_child_flags
Definition: pmsignal.c:77
#define ERROR
Definition: elog.h:46
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:396
#define FATAL
Definition: elog.h:49
void SetQuitSignalReason(QuitSignalReason reason)
Definition: pmsignal.c:190
void PMSignalShmemInit(void)
Definition: pmsignal.c:134
char * c
bool IsUnderPostmaster
Definition: globals.c:112
pid_t PostmasterPid
Definition: globals.c:98
int postmaster_alive_fds[2]
Definition: postmaster.c:571
sig_atomic_t PMSignalFlags[NUM_PMSIGNALS]
Definition: pmsignal.c:73
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
bool PostmasterIsAliveInternal(void)
Definition: pmsignal.c:344
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:170
int MaxLivePostmasterChildren(void)
Definition: postmaster.c:5725
#define Assert(condition)
Definition: c.h:804
size_t Size
Definition: c.h:540
#define PM_CHILD_UNUSED
Definition: pmsignal.c:64
PMSignalReason
Definition: pmsignal.h:33
int MyPMChildSlot
Definition: globals.c:48
#define unvolatize(underlying_type, expr)
Definition: c.h:1245
#define elog(elevel,...)
Definition: elog.h:232
#define EWOULDBLOCK
Definition: win32_port.h:349
void PostmasterDeathSignalInit(void)
Definition: pmsignal.c:405
void SendPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:153
sig_atomic_t PMChildFlags[FLEXIBLE_ARRAY_MEMBER]
Definition: pmsignal.c:79
bool IsPostmasterChildWalSender(int slot)
Definition: pmsignal.c:275
#define POSTMASTER_FD_WATCH
Definition: postmaster.h:43
#define read(a, b, c)
Definition: win32.h:13
#define offsetof(type, field)
Definition: c.h:727
#define PM_CHILD_WALSENDER
Definition: pmsignal.c:67
void MarkPostmasterChildActive(void)
Definition: pmsignal.c:291
#define NON_EXEC_STATIC
Definition: c.h:1358