1 /*-------------------------------------------------------------------------
4 * routines for signaling the postmaster from its child processes
7 * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/storage/ipc/pmsignal.c
13 *-------------------------------------------------------------------------
20 #include "miscadmin.h"
21 #include "postmaster/postmaster.h"
22 #include "replication/walsender.h"
23 #include "storage/pmsignal.h"
24 #include "storage/shmem.h"
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.)
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.
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.
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.
54 #define PM_CHILD_UNUSED 0 /* these values must fit in sig_atomic_t */
55 #define PM_CHILD_ASSIGNED 1
56 #define PM_CHILD_ACTIVE 2
57 #define PM_CHILD_WALSENDER 3
59 /* "typedef struct PMSignalData PMSignalData" appears in pmsignal.h */
62 /* per-reason flags */
63 sig_atomic_t PMSignalFlags[NUM_PMSIGNALS];
64 /* per-child-process flags */
65 int num_child_flags; /* # of entries in PMChildFlags[] */
66 int next_child_flag; /* next slot to try to assign */
67 sig_atomic_t PMChildFlags[1]; /* VARIABLE LENGTH ARRAY */
70 NON_EXEC_STATIC volatile PMSignalData *PMSignalState = NULL;
75 * Compute space needed for pmsignal.c's shared memory
78 PMSignalShmemSize(void)
82 size = offsetof(PMSignalData, PMChildFlags);
83 size = add_size(size, mul_size(MaxLivePostmasterChildren(),
84 sizeof(sig_atomic_t)));
90 * PMSignalShmemInit - initialize during shared-memory creation
93 PMSignalShmemInit(void)
97 PMSignalState = (PMSignalData *)
98 ShmemInitStruct("PMSignalState", PMSignalShmemSize(), &found);
102 MemSet(PMSignalState, 0, PMSignalShmemSize());
103 PMSignalState->num_child_flags = MaxLivePostmasterChildren();
108 * SendPostmasterSignal - signal the postmaster from a child process
111 SendPostmasterSignal(PMSignalReason reason)
113 /* If called in a standalone backend, do nothing */
114 if (!IsUnderPostmaster)
116 /* Atomically set the proper flag */
117 PMSignalState->PMSignalFlags[reason] = true;
118 /* Send signal to postmaster */
119 kill(PostmasterPid, SIGUSR1);
123 * CheckPostmasterSignal - check to see if a particular reason has been
124 * signaled, and clear the signal flag. Should be called by postmaster
125 * after receiving SIGUSR1.
128 CheckPostmasterSignal(PMSignalReason reason)
130 /* Careful here --- don't clear flag if we haven't seen it set */
131 if (PMSignalState->PMSignalFlags[reason])
133 PMSignalState->PMSignalFlags[reason] = false;
141 * AssignPostmasterChildSlot - select an unused slot for a new postmaster
142 * child process, and set its state to ASSIGNED. Returns a slot number
145 * Only the postmaster is allowed to execute this routine, so we need no
149 AssignPostmasterChildSlot(void)
151 int slot = PMSignalState->next_child_flag;
155 * Scan for a free slot. We track the last slot assigned so as not to
156 * waste time repeatedly rescanning low-numbered slots.
158 for (n = PMSignalState->num_child_flags; n > 0; n--)
161 slot = PMSignalState->num_child_flags - 1;
162 if (PMSignalState->PMChildFlags[slot] == PM_CHILD_UNUSED)
164 PMSignalState->PMChildFlags[slot] = PM_CHILD_ASSIGNED;
165 PMSignalState->next_child_flag = slot;
170 /* Out of slots ... should never happen, else postmaster.c messed up */
171 elog(FATAL, "no free slots in PMChildFlags array");
172 return 0; /* keep compiler quiet */
176 * ReleasePostmasterChildSlot - release a slot after death of a postmaster
177 * child process. This must be called in the postmaster process.
179 * Returns true if the slot had been in ASSIGNED state (the expected case),
180 * false otherwise (implying that the child failed to clean itself up).
183 ReleasePostmasterChildSlot(int slot)
187 Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
191 * Note: the slot state might already be unused, because the logic in
192 * postmaster.c is such that this might get called twice when a child
193 * crashes. So we don't try to Assert anything about the state.
195 result = (PMSignalState->PMChildFlags[slot] == PM_CHILD_ASSIGNED);
196 PMSignalState->PMChildFlags[slot] = PM_CHILD_UNUSED;
201 * IsPostmasterChildWalSender - check if given slot is in use by a
205 IsPostmasterChildWalSender(int slot)
207 Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
210 if (PMSignalState->PMChildFlags[slot] == PM_CHILD_WALSENDER)
217 * MarkPostmasterChildActive - mark a postmaster child as about to begin
218 * actively using shared memory. This is called in the child process.
221 MarkPostmasterChildActive(void)
223 int slot = MyPMChildSlot;
225 Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
227 Assert(PMSignalState->PMChildFlags[slot] == PM_CHILD_ASSIGNED);
228 PMSignalState->PMChildFlags[slot] =
229 (am_walsender ? PM_CHILD_WALSENDER : PM_CHILD_ACTIVE);
233 * MarkPostmasterChildInactive - mark a postmaster child as done using
234 * shared memory. This is called in the child process.
237 MarkPostmasterChildInactive(void)
239 int slot = MyPMChildSlot;
241 Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
243 Assert(PMSignalState->PMChildFlags[slot] == PM_CHILD_ACTIVE ||
244 PMSignalState->PMChildFlags[slot] == PM_CHILD_WALSENDER);
245 PMSignalState->PMChildFlags[slot] = PM_CHILD_ASSIGNED;
250 * PostmasterIsAlive - check whether postmaster process is still alive
252 * amDirectChild should be passed as "true" by code that knows it is
253 * executing in a direct child process of the postmaster; pass "false"
254 * if an indirect child or not sure. The "true" case uses a faster and
255 * more reliable test, so use it when possible.
258 PostmasterIsAlive(bool amDirectChild)
263 pid_t ppid = getppid();
265 /* If the postmaster is still our parent, it must be alive. */
266 if (ppid == PostmasterPid)
269 /* If the init process is our parent, postmaster must be dead. */
274 * If we get here, our parent process is neither the postmaster nor
275 * init. This can occur on BSD and MacOS systems if a debugger has
276 * been attached. We fall through to the less-reliable kill() method.
281 * Use kill() to see if the postmaster is still alive. This can
282 * sometimes give a false positive result, since the postmaster's PID
283 * may get recycled, but it is good enough for existing uses by
284 * indirect children and in debugging environments.
286 return (kill(PostmasterPid, 0) == 0);
288 return (WaitForSingleObject(PostmasterHandle, 0) == WAIT_TIMEOUT);