1/*-------------------------------------------------------------------------
4 * Functions for keeping track of postmaster child processes.
6 * Postmaster keeps track of all child processes so that when a process exits,
7 * it knows what kind of a process it was and can clean up accordingly. Every
8 * child process is allocated a PMChild struct from a fixed pool of structs.
9 * The size of the pool is determined by various settings that configure how
10 * many worker processes and backend connections are allowed, i.e.
11 * autovacuum_worker_slots, max_worker_processes, max_wal_senders, and
14 * Dead-end backends are handled slightly differently. There is no limit
15 * on the number of dead-end backends, and they do not need unique IDs, so
16 * their PMChild structs are allocated dynamically, not from a pool.
18 * The structures and functions in this file are private to the postmaster
19 * process. But note that there is an array in shared memory, managed by
20 * pmsignal.c, that mirrors this.
23 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
24 * Portions Copyright (c) 1994, Regents of the University of California
27 * src/backend/postmaster/pmchild.c
29 *-------------------------------------------------------------------------
42 * Freelists for different kinds of child processes. We maintain separate
43 * pools for each, so that for example launching a lot of regular backends
44 * cannot prevent autovacuum or an aux process from launching.
48 int size;
/* number of PMChild slots reserved for this
49 * kind of processes */
58 * List of active child processes. This includes dead-end children.
63 * Dummy pointer to persuade Valgrind that we've not leaked the array of
64 * PMChild structs. Make it global to ensure the compiler doesn't
74 * MaxLivePostmasterChildren
76 * This reports the number of postmaster child processes that can be active.
77 * It includes all children except for dead-end children. This allows the
78 * array in shared memory (PMChildFlags) to have a fixed maximum size.
84 elog(
ERROR,
"PM child array not initialized yet");
89 * Initialize at postmaster startup
91 * Note: This is not called on crash restart. We rely on PMChild entries to
92 * remain valid through the restart process. This is important because the
93 * syslogger survives through the crash restart process, so we must not
94 * invalidate its PMChild slot.
103 * We allow more connections here than we can have backends because some
104 * might still be authenticating; they might fail auth, or some existing
105 * backend might exit before the auth cycle is completed. The exact
106 * MaxConnections limit is enforced when a new backend tries to join the
109 * WAL senders start out as regular backends, so they share the same pool.
118 * There can be only one of each of these running at a time. They each
119 * get their own pool of just one entry.
132 /* The rest of the pmchild_pools are left at zero size */
134 /* Count the total number of slots */
139 /* Allocate enough slots, and make sure Valgrind doesn't complain */
142 pmchild_array = slots;
145 /* Initialize them */
154 slots[slotno].
pid = 0;
157 slots[slotno].
rw = NULL;
165 /* Initialize other structures */
170 * Allocate a PMChild entry for a postmaster child process of given type.
172 * The entry is taken from the right pool for the type.
174 * pmchild->child_slot in the returned struct is unique among all active child
184 elog(
ERROR,
"cannot allocate a PMChild slot for backend type %d", btype);
197 * pmchild->child_slot for each entry was initialized when the array of
198 * slots was allocated. Sanity check it.
203 elog(
ERROR,
"pmchild freelist for backend type %d is corrupt",
209 /* Update the status in the shared memory array */
212 elog(
DEBUG2,
"assigned pm child slot %d for %s",
219 * Allocate a PMChild struct for a dead-end backend. Dead-end children are
220 * not assigned a child_slot number. The struct is palloc'd; returns NULL if
246 * Release a PMChild slot, after the child process has exited.
248 * Returns true if the child detached cleanly from shared memory, false
249 * otherwise (see MarkPostmasterChildSlotUnassigned).
267 /* WAL senders start out as regular backends, and share the pool */
273 /* sanity check that we return the entry to the right pool */
277 elog(
ERROR,
"pmchild freelist for backend type %d is corrupt",
287 * Find the PMChild entry of a running child process by PID.
int autovacuum_worker_slots
#define MCXT_ALLOC_NO_OOM
Assert(PointerIsAligned(start, uint64))
static dlist_node * dlist_pop_head_node(dlist_head *head)
#define dlist_foreach(iter, lhead)
static void dlist_init(dlist_head *head)
static void dlist_delete(dlist_node *node)
static void dlist_push_head(dlist_head *head, dlist_node *node)
static bool dlist_is_empty(const dlist_head *head)
static void dlist_push_tail(dlist_head *head, dlist_node *node)
#define dlist_container(type, membername, ptr)
const char * PostmasterChildName(BackendType child_type)
void pfree(void *pointer)
void * palloc_extended(Size size, int flags)
#define BACKEND_NUM_TYPES
NON_EXEC_STATIC int num_pmchild_slots
PMChild * AssignPostmasterChildSlot(BackendType btype)
bool ReleasePostmasterChildSlot(PMChild *pmchild)
static PMChildPool pmchild_pools[BACKEND_NUM_TYPES]
void InitPostmasterChildSlots(void)
PMChild * AllocDeadEndChild(void)
int MaxLivePostmasterChildren(void)
dlist_head ActiveChildList
PMChild * FindPostmasterChildByPid(int pid)
struct PMChildPool PMChildPool
void MarkPostmasterChildSlotAssigned(int slot)
bool MarkPostmasterChildSlotUnassigned(int slot)
struct RegisteredBgWorker * rw