PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pmsignal.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * pmsignal.c
4  * routines for signaling the postmaster from its child processes
5  *
6  *
7  * Portions Copyright (c) 1996-2017, 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 #include "miscadmin.h"
21 #include "postmaster/postmaster.h"
22 #include "replication/walsender.h"
23 #include "storage/pmsignal.h"
24 #include "storage/shmem.h"
25 
26 
27 /*
28  * The postmaster is signaled by its children by sending SIGUSR1. The
29  * specific reason is communicated via flags in shared memory. We keep
30  * a boolean flag for each possible "reason", so that different reasons
31  * can be signaled by different backends at the same time. (However,
32  * if the same reason is signaled more than once simultaneously, the
33  * postmaster will observe it only once.)
34  *
35  * The flags are actually declared as "volatile sig_atomic_t" for maximum
36  * portability. This should ensure that loads and stores of the flag
37  * values are atomic, allowing us to dispense with any explicit locking.
38  *
39  * In addition to the per-reason flags, we store a set of per-child-process
40  * flags that are currently used only for detecting whether a backend has
41  * exited without performing proper shutdown. The per-child-process flags
42  * have three possible states: UNUSED, ASSIGNED, ACTIVE. An UNUSED slot is
43  * available for assignment. An ASSIGNED slot is associated with a postmaster
44  * child process, but either the process has not touched shared memory yet,
45  * or it has successfully cleaned up after itself. A ACTIVE slot means the
46  * process is actively using shared memory. The slots are assigned to
47  * child processes at random, and postmaster.c is responsible for tracking
48  * which one goes with which PID.
49  *
50  * Actually there is a fourth state, WALSENDER. This is just like ACTIVE,
51  * but carries the extra information that the child is a WAL sender.
52  * WAL senders too start in ACTIVE state, but switch to WALSENDER once they
53  * start streaming the WAL (and they never go back to ACTIVE after that).
54  */
55 
56 #define PM_CHILD_UNUSED 0 /* these values must fit in sig_atomic_t */
57 #define PM_CHILD_ASSIGNED 1
58 #define PM_CHILD_ACTIVE 2
59 #define PM_CHILD_WALSENDER 3
60 
61 /* "typedef struct PMSignalData PMSignalData" appears in pmsignal.h */
63 {
64  /* per-reason flags */
66  /* per-child-process flags */
67  int num_child_flags; /* # of entries in PMChildFlags[] */
68  int next_child_flag; /* next slot to try to assign */
69  sig_atomic_t PMChildFlags[FLEXIBLE_ARRAY_MEMBER];
70 };
71 
73 
74 
75 /*
76  * PMSignalShmemSize
77  * Compute space needed for pmsignal.c's shared memory
78  */
79 Size
81 {
82  Size size;
83 
84  size = offsetof(PMSignalData, PMChildFlags);
86  sizeof(sig_atomic_t)));
87 
88  return size;
89 }
90 
91 /*
92  * PMSignalShmemInit - initialize during shared-memory creation
93  */
94 void
96 {
97  bool found;
98 
100  ShmemInitStruct("PMSignalState", PMSignalShmemSize(), &found);
101 
102  if (!found)
103  {
106  }
107 }
108 
109 /*
110  * SendPostmasterSignal - signal the postmaster from a child process
111  */
112 void
114 {
115  /* If called in a standalone backend, do nothing */
116  if (!IsUnderPostmaster)
117  return;
118  /* Atomically set the proper flag */
119  PMSignalState->PMSignalFlags[reason] = true;
120  /* Send signal to postmaster */
121  kill(PostmasterPid, SIGUSR1);
122 }
123 
124 /*
125  * CheckPostmasterSignal - check to see if a particular reason has been
126  * signaled, and clear the signal flag. Should be called by postmaster
127  * after receiving SIGUSR1.
128  */
129 bool
131 {
132  /* Careful here --- don't clear flag if we haven't seen it set */
133  if (PMSignalState->PMSignalFlags[reason])
134  {
135  PMSignalState->PMSignalFlags[reason] = false;
136  return true;
137  }
138  return false;
139 }
140 
141 
142 /*
143  * AssignPostmasterChildSlot - select an unused slot for a new postmaster
144  * child process, and set its state to ASSIGNED. Returns a slot number
145  * (one to N).
146  *
147  * Only the postmaster is allowed to execute this routine, so we need no
148  * special locking.
149  */
150 int
152 {
153  int slot = PMSignalState->next_child_flag;
154  int n;
155 
156  /*
157  * Scan for a free slot. We track the last slot assigned so as not to
158  * waste time repeatedly rescanning low-numbered slots.
159  */
160  for (n = PMSignalState->num_child_flags; n > 0; n--)
161  {
162  if (--slot < 0)
163  slot = PMSignalState->num_child_flags - 1;
165  {
168  return slot + 1;
169  }
170  }
171 
172  /* Out of slots ... should never happen, else postmaster.c messed up */
173  elog(FATAL, "no free slots in PMChildFlags array");
174  return 0; /* keep compiler quiet */
175 }
176 
177 /*
178  * ReleasePostmasterChildSlot - release a slot after death of a postmaster
179  * child process. This must be called in the postmaster process.
180  *
181  * Returns true if the slot had been in ASSIGNED state (the expected case),
182  * false otherwise (implying that the child failed to clean itself up).
183  */
184 bool
186 {
187  bool result;
188 
189  Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
190  slot--;
191 
192  /*
193  * Note: the slot state might already be unused, because the logic in
194  * postmaster.c is such that this might get called twice when a child
195  * crashes. So we don't try to Assert anything about the state.
196  */
197  result = (PMSignalState->PMChildFlags[slot] == PM_CHILD_ASSIGNED);
199  return result;
200 }
201 
202 /*
203  * IsPostmasterChildWalSender - check if given slot is in use by a
204  * walsender process.
205  */
206 bool
208 {
209  Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
210  slot--;
211 
213  return true;
214  else
215  return false;
216 }
217 
218 /*
219  * MarkPostmasterChildActive - mark a postmaster child as about to begin
220  * actively using shared memory. This is called in the child process.
221  */
222 void
224 {
225  int slot = MyPMChildSlot;
226 
227  Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
228  slot--;
231 }
232 
233 /*
234  * MarkPostmasterChildWalSender - mark a postmaster child as a WAL sender
235  * process. This is called in the child process, sometime after marking the
236  * child as active.
237  */
238 void
240 {
241  int slot = MyPMChildSlot;
242 
244 
245  Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
246  slot--;
249 }
250 
251 /*
252  * MarkPostmasterChildInactive - mark a postmaster child as done using
253  * shared memory. This is called in the child process.
254  */
255 void
257 {
258  int slot = MyPMChildSlot;
259 
260  Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
261  slot--;
265 }
266 
267 
268 /*
269  * PostmasterIsAlive - check whether postmaster process is still alive
270  */
271 bool
273 {
274 #ifndef WIN32
275  char c;
276  ssize_t rc;
277 
279  if (rc < 0)
280  {
281  if (errno == EAGAIN || errno == EWOULDBLOCK)
282  return true;
283  else
284  elog(FATAL, "read on postmaster death monitoring pipe failed: %m");
285  }
286  else if (rc > 0)
287  elog(FATAL, "unexpected data in postmaster death monitoring pipe");
288 
289  return false;
290 #else /* WIN32 */
291  return (WaitForSingleObject(PostmasterHandle, 0) == WAIT_TIMEOUT);
292 #endif /* WIN32 */
293 }
#define EWOULDBLOCK
Definition: win32.h:301
int next_child_flag
Definition: pmsignal.c:68
#define SIGUSR1
Definition: win32.h:211
Size PMSignalShmemSize(void)
Definition: pmsignal.c:80
bool CheckPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:130
NON_EXEC_STATIC volatile PMSignalData * PMSignalState
Definition: pmsignal.c:72
void MarkPostmasterChildWalSender(void)
Definition: pmsignal.c:239
#define PM_CHILD_ACTIVE
Definition: pmsignal.c:58
#define PM_CHILD_ASSIGNED
Definition: pmsignal.c:57
#define MemSet(start, val, len)
Definition: c.h:857
void MarkPostmasterChildInactive(void)
Definition: pmsignal.c:256
return result
Definition: formatting.c:1618
bool ReleasePostmasterChildSlot(int slot)
Definition: pmsignal.c:185
int AssignPostmasterChildSlot(void)
Definition: pmsignal.c:151
#define EAGAIN
Definition: win32.h:293
bool am_walsender
Definition: walsender.c:108
int num_child_flags
Definition: pmsignal.c:67
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:372
#define FATAL
Definition: elog.h:52
void PMSignalShmemInit(void)
Definition: pmsignal.c:95
char * c
bool IsUnderPostmaster
Definition: globals.c:100
bool PostmasterIsAlive(void)
Definition: pmsignal.c:272
pid_t PostmasterPid
Definition: globals.c:86
int postmaster_alive_fds[2]
Definition: postmaster.c:556
sig_atomic_t PMSignalFlags[NUM_PMSIGNALS]
Definition: pmsignal.c:65
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
#define NULL
Definition: c.h:229
int MaxLivePostmasterChildren(void)
Definition: postmaster.c:5442
#define Assert(condition)
Definition: c.h:675
size_t Size
Definition: c.h:356
#define PM_CHILD_UNUSED
Definition: pmsignal.c:56
PMSignalReason
Definition: pmsignal.h:23
int MyPMChildSlot
Definition: globals.c:42
void SendPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:113
#define elog
Definition: elog.h:219
sig_atomic_t PMChildFlags[FLEXIBLE_ARRAY_MEMBER]
Definition: pmsignal.c:69
bool IsPostmasterChildWalSender(int slot)
Definition: pmsignal.c:207
#define POSTMASTER_FD_WATCH
Definition: postmaster.h:42
#define read(a, b, c)
Definition: win32.h:18
#define offsetof(type, field)
Definition: c.h:555
#define PM_CHILD_WALSENDER
Definition: pmsignal.c:59
void MarkPostmasterChildActive(void)
Definition: pmsignal.c:223
#define NON_EXEC_STATIC
Definition: c.h:1121