1 /*-------------------------------------------------------------------------
4 * routines for signaling between the postmaster and its child processes
7 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/storage/ipc/pmsignal.c
13 *-------------------------------------------------------------------------
20 #ifdef HAVE_SYS_PRCTL_H
21 #include <sys/prctl.h>
24 #include "miscadmin.h"
25 #include "postmaster/postmaster.h"
26 #include "replication/walsender.h"
27 #include "storage/ipc.h"
28 #include "storage/pmsignal.h"
29 #include "storage/shmem.h"
30 #include "utils/memutils.h"
34 * The postmaster is signaled by its children by sending SIGUSR1. The
35 * specific reason is communicated via flags in shared memory. We keep
36 * a boolean flag for each possible "reason", so that different reasons
37 * can be signaled by different backends at the same time. (However,
38 * if the same reason is signaled more than once simultaneously, the
39 * postmaster will observe it only once.)
41 * The flags are actually declared as "volatile sig_atomic_t" for maximum
42 * portability. This should ensure that loads and stores of the flag
43 * values are atomic, allowing us to dispense with any explicit locking.
45 * In addition to the per-reason flags, we store a set of per-child-process
46 * flags that are currently used only for detecting whether a backend has
47 * exited without performing proper shutdown. The per-child-process flags
48 * have three possible states: UNUSED, ASSIGNED, ACTIVE. An UNUSED slot is
49 * available for assignment. An ASSIGNED slot is associated with a postmaster
50 * child process, but either the process has not touched shared memory yet, or
51 * it has successfully cleaned up after itself. An ACTIVE slot means the
52 * process is actively using shared memory. The slots are assigned to child
53 * processes by postmaster, and pmchild.c is responsible for tracking which
54 * one goes with which PID.
56 * Actually there is a fourth state, WALSENDER. This is just like ACTIVE,
57 * but carries the extra information that the child is a WAL sender.
58 * WAL senders too start in ACTIVE state, but switch to WALSENDER once they
59 * start streaming the WAL (and they never go back to ACTIVE after that).
61 * We also have a shared-memory field that is used for communication in
62 * the opposite direction, from postmaster to children: it tells why the
63 * postmaster has broadcasted SIGQUIT signals, if indeed it has done so.
66 #define PM_CHILD_UNUSED 0 /* these values must fit in sig_atomic_t */
67 #define PM_CHILD_ASSIGNED 1
68 #define PM_CHILD_ACTIVE 2
69 #define PM_CHILD_WALSENDER 3
71 /* "typedef struct PMSignalData PMSignalData" appears in pmsignal.h */
74 /* per-reason flags for signaling the postmaster */
75 sig_atomic_t PMSignalFlags
[NUM_PMSIGNALS
];
76 /* global flags for signals from postmaster to children */
77 QuitSignalReason sigquit_reason
; /* why SIGQUIT was sent */
78 /* per-child-process flags */
79 int num_child_flags
; /* # of entries in PMChildFlags[] */
80 sig_atomic_t PMChildFlags
[FLEXIBLE_ARRAY_MEMBER
];
83 /* PMSignalState pointer is valid in both postmaster and child processes */
84 NON_EXEC_STATIC
volatile PMSignalData
*PMSignalState
= NULL
;
87 * Local copy of PMSignalState->num_child_flags, only valid in the
88 * postmaster. Postmaster keeps a local copy so that it doesn't need to
89 * trust the value in shared memory.
91 static int num_child_flags
;
94 * Signal handler to be notified if postmaster dies.
96 #ifdef USE_POSTMASTER_DEATH_SIGNAL
97 volatile sig_atomic_t postmaster_possibly_dead
= false;
100 postmaster_death_handler(SIGNAL_ARGS
)
102 postmaster_possibly_dead
= true;
106 * The available signals depend on the OS. SIGUSR1 and SIGUSR2 are already
107 * used for other things, so choose another one.
109 * Currently, we assume that we can always find a signal to use. That
110 * seems like a reasonable assumption for all platforms that are modern
111 * enough to have a parent-death signaling mechanism.
114 #define POSTMASTER_DEATH_SIGNAL SIGINFO
115 #elif defined(SIGPWR)
116 #define POSTMASTER_DEATH_SIGNAL SIGPWR
118 #error "cannot find a signal to use for postmaster death"
121 #endif /* USE_POSTMASTER_DEATH_SIGNAL */
123 static void MarkPostmasterChildInactive(int code
, Datum arg
);
127 * Compute space needed for pmsignal.c's shared memory
130 PMSignalShmemSize(void)
134 size
= offsetof(PMSignalData
, PMChildFlags
);
135 size
= add_size(size
, mul_size(MaxLivePostmasterChildren(),
136 sizeof(sig_atomic_t)));
142 * PMSignalShmemInit - initialize during shared-memory creation
145 PMSignalShmemInit(void)
149 PMSignalState
= (PMSignalData
*)
150 ShmemInitStruct("PMSignalState", PMSignalShmemSize(), &found
);
154 /* initialize all flags to zeroes */
155 MemSet(unvolatize(PMSignalData
*, PMSignalState
), 0, PMSignalShmemSize());
156 num_child_flags
= MaxLivePostmasterChildren();
157 PMSignalState
->num_child_flags
= num_child_flags
;
162 * SendPostmasterSignal - signal the postmaster from a child process
165 SendPostmasterSignal(PMSignalReason reason
)
167 /* If called in a standalone backend, do nothing */
168 if (!IsUnderPostmaster
)
170 /* Atomically set the proper flag */
171 PMSignalState
->PMSignalFlags
[reason
] = true;
172 /* Send signal to postmaster */
173 kill(PostmasterPid
, SIGUSR1
);
177 * CheckPostmasterSignal - check to see if a particular reason has been
178 * signaled, and clear the signal flag. Should be called by postmaster
179 * after receiving SIGUSR1.
182 CheckPostmasterSignal(PMSignalReason reason
)
184 /* Careful here --- don't clear flag if we haven't seen it set */
185 if (PMSignalState
->PMSignalFlags
[reason
])
187 PMSignalState
->PMSignalFlags
[reason
] = false;
194 * SetQuitSignalReason - broadcast the reason for a system shutdown.
195 * Should be called by postmaster before sending SIGQUIT to children.
197 * Note: in a crash-and-restart scenario, the "reason" field gets cleared
198 * as a part of rebuilding shared memory; the postmaster need not do it
202 SetQuitSignalReason(QuitSignalReason reason
)
204 PMSignalState
->sigquit_reason
= reason
;
208 * GetQuitSignalReason - obtain the reason for a system shutdown.
209 * Called by child processes when they receive SIGQUIT.
210 * If the postmaster hasn't actually sent SIGQUIT, will return PMQUIT_NOT_SENT.
213 GetQuitSignalReason(void)
215 /* This is called in signal handlers, so be extra paranoid. */
216 if (!IsUnderPostmaster
|| PMSignalState
== NULL
)
217 return PMQUIT_NOT_SENT
;
218 return PMSignalState
->sigquit_reason
;
223 * MarkPostmasterChildSlotAssigned - mark the given slot as ASSIGNED for a
224 * new postmaster child process.
226 * Only the postmaster is allowed to execute this routine, so we need no
230 MarkPostmasterChildSlotAssigned(int slot
)
232 Assert(slot
> 0 && slot
<= num_child_flags
);
235 if (PMSignalState
->PMChildFlags
[slot
] != PM_CHILD_UNUSED
)
236 elog(FATAL
, "postmaster child slot is already in use");
238 PMSignalState
->PMChildFlags
[slot
] = PM_CHILD_ASSIGNED
;
242 * MarkPostmasterChildSlotUnassigned - release a slot after death of a
243 * postmaster child process. This must be called in the postmaster process.
245 * Returns true if the slot had been in ASSIGNED state (the expected case),
246 * false otherwise (implying that the child failed to clean itself up).
249 MarkPostmasterChildSlotUnassigned(int slot
)
253 Assert(slot
> 0 && slot
<= num_child_flags
);
257 * Note: the slot state might already be unused, because the logic in
258 * postmaster.c is such that this might get called twice when a child
259 * crashes. So we don't try to Assert anything about the state.
261 result
= (PMSignalState
->PMChildFlags
[slot
] == PM_CHILD_ASSIGNED
);
262 PMSignalState
->PMChildFlags
[slot
] = PM_CHILD_UNUSED
;
267 * IsPostmasterChildWalSender - check if given slot is in use by a
268 * walsender process. This is called only by the postmaster.
271 IsPostmasterChildWalSender(int slot
)
273 Assert(slot
> 0 && slot
<= num_child_flags
);
276 if (PMSignalState
->PMChildFlags
[slot
] == PM_CHILD_WALSENDER
)
283 * RegisterPostmasterChildActive - mark a postmaster child as about to begin
284 * actively using shared memory. This is called in the child process.
286 * This register an shmem exit hook to mark us as inactive again when the
287 * process exits normally.
290 RegisterPostmasterChildActive(void)
292 int slot
= MyPMChildSlot
;
294 Assert(slot
> 0 && slot
<= PMSignalState
->num_child_flags
);
296 Assert(PMSignalState
->PMChildFlags
[slot
] == PM_CHILD_ASSIGNED
);
297 PMSignalState
->PMChildFlags
[slot
] = PM_CHILD_ACTIVE
;
299 /* Arrange to clean up at exit. */
300 on_shmem_exit(MarkPostmasterChildInactive
, 0);
304 * MarkPostmasterChildWalSender - mark a postmaster child as a WAL sender
305 * process. This is called in the child process, sometime after marking the
309 MarkPostmasterChildWalSender(void)
311 int slot
= MyPMChildSlot
;
313 Assert(am_walsender
);
315 Assert(slot
> 0 && slot
<= PMSignalState
->num_child_flags
);
317 Assert(PMSignalState
->PMChildFlags
[slot
] == PM_CHILD_ACTIVE
);
318 PMSignalState
->PMChildFlags
[slot
] = PM_CHILD_WALSENDER
;
322 * MarkPostmasterChildInactive - mark a postmaster child as done using
323 * shared memory. This is called in the child process.
326 MarkPostmasterChildInactive(int code
, Datum arg
)
328 int slot
= MyPMChildSlot
;
330 Assert(slot
> 0 && slot
<= PMSignalState
->num_child_flags
);
332 Assert(PMSignalState
->PMChildFlags
[slot
] == PM_CHILD_ACTIVE
||
333 PMSignalState
->PMChildFlags
[slot
] == PM_CHILD_WALSENDER
);
334 PMSignalState
->PMChildFlags
[slot
] = PM_CHILD_ASSIGNED
;
339 * PostmasterIsAliveInternal - check whether postmaster process is still alive
341 * This is the slow path of PostmasterIsAlive(), where the caller has already
342 * checked 'postmaster_possibly_dead'. (On platforms that don't support
343 * a signal for parent death, PostmasterIsAlive() is just an alias for this.)
346 PostmasterIsAliveInternal(void)
348 #ifdef USE_POSTMASTER_DEATH_SIGNAL
350 * Reset the flag before checking, so that we don't miss a signal if
351 * postmaster dies right after the check. If postmaster was indeed dead,
352 * we'll re-arm it before returning to caller.
354 postmaster_possibly_dead
= false;
362 rc
= read(postmaster_alive_fds
[POSTMASTER_FD_WATCH
], &c
, 1);
365 * In the usual case, the postmaster is still alive, and there is no
368 if (rc
< 0 && (errno
== EAGAIN
|| errno
== EWOULDBLOCK
))
373 * Postmaster is dead, or something went wrong with the read()
377 #ifdef USE_POSTMASTER_DEATH_SIGNAL
378 postmaster_possibly_dead
= true;
382 elog(FATAL
, "read on postmaster death monitoring pipe failed: %m");
384 elog(FATAL
, "unexpected data in postmaster death monitoring pipe");
391 if (WaitForSingleObject(PostmasterHandle
, 0) == WAIT_TIMEOUT
)
395 #ifdef USE_POSTMASTER_DEATH_SIGNAL
396 postmaster_possibly_dead
= true;
404 * PostmasterDeathSignalInit - request signal on postmaster death if possible
407 PostmasterDeathSignalInit(void)
409 #ifdef USE_POSTMASTER_DEATH_SIGNAL
410 int signum
= POSTMASTER_DEATH_SIGNAL
;
412 /* Register our signal handler. */
413 pqsignal(signum
, postmaster_death_handler
);
415 /* Request a signal on parent exit. */
416 #if defined(PR_SET_PDEATHSIG)
417 if (prctl(PR_SET_PDEATHSIG
, signum
) < 0)
418 elog(ERROR
, "could not request parent death signal: %m");
419 #elif defined(PROC_PDEATHSIG_CTL)
420 if (procctl(P_PID
, 0, PROC_PDEATHSIG_CTL
, &signum
) < 0)
421 elog(ERROR
, "could not request parent death signal: %m");
423 #error "USE_POSTMASTER_DEATH_SIGNAL set, but there is no mechanism to request the signal"
427 * Just in case the parent was gone already and we missed it, we'd better
428 * check the slow way on the first call.
430 postmaster_possibly_dead
= true;
431 #endif /* USE_POSTMASTER_DEATH_SIGNAL */