PostgreSQL Source Code  git master
pmsignal.c File Reference
#include "postgres.h"
#include <signal.h>
#include <unistd.h>
#include "miscadmin.h"
#include "postmaster/postmaster.h"
#include "replication/walsender.h"
#include "storage/ipc.h"
#include "storage/pmsignal.h"
#include "storage/shmem.h"
#include "utils/memutils.h"
Include dependency graph for pmsignal.c:

Go to the source code of this file.

Data Structures

struct  PMSignalData
 

Macros

#define PM_CHILD_UNUSED   0 /* these values must fit in sig_atomic_t */
 
#define PM_CHILD_ASSIGNED   1
 
#define PM_CHILD_ACTIVE   2
 
#define PM_CHILD_WALSENDER   3
 

Functions

static void MarkPostmasterChildInactive (int code, Datum arg)
 
Size PMSignalShmemSize (void)
 
void PMSignalShmemInit (void)
 
void SendPostmasterSignal (PMSignalReason reason)
 
bool CheckPostmasterSignal (PMSignalReason reason)
 
void SetQuitSignalReason (QuitSignalReason reason)
 
QuitSignalReason GetQuitSignalReason (void)
 
int AssignPostmasterChildSlot (void)
 
bool ReleasePostmasterChildSlot (int slot)
 
bool IsPostmasterChildWalSender (int slot)
 
void RegisterPostmasterChildActive (void)
 
void MarkPostmasterChildWalSender (void)
 
bool PostmasterIsAliveInternal (void)
 
void PostmasterDeathSignalInit (void)
 

Variables

NON_EXEC_STATIC volatile PMSignalDataPMSignalState = NULL
 
static int num_child_inuse
 
static int next_child_inuse
 
static boolPMChildInUse
 

Macro Definition Documentation

◆ PM_CHILD_ACTIVE

#define PM_CHILD_ACTIVE   2

Definition at line 68 of file pmsignal.c.

◆ PM_CHILD_ASSIGNED

#define PM_CHILD_ASSIGNED   1

Definition at line 67 of file pmsignal.c.

◆ PM_CHILD_UNUSED

#define PM_CHILD_UNUSED   0 /* these values must fit in sig_atomic_t */

Definition at line 66 of file pmsignal.c.

◆ PM_CHILD_WALSENDER

#define PM_CHILD_WALSENDER   3

Definition at line 69 of file pmsignal.c.

Function Documentation

◆ AssignPostmasterChildSlot()

int AssignPostmasterChildSlot ( void  )

Definition at line 250 of file pmsignal.c.

251 {
252  int slot = next_child_inuse;
253  int n;
254 
255  /*
256  * Scan for a free slot. Notice that we trust nothing about the contents
257  * of PMSignalState, but use only postmaster-local data for this decision.
258  * We track the last slot assigned so as not to waste time repeatedly
259  * rescanning low-numbered slots.
260  */
261  for (n = num_child_inuse; n > 0; n--)
262  {
263  if (--slot < 0)
264  slot = num_child_inuse - 1;
265  if (!PMChildInUse[slot])
266  {
267  PMChildInUse[slot] = true;
269  next_child_inuse = slot;
270  return slot + 1;
271  }
272  }
273 
274  /* Out of slots ... should never happen, else postmaster.c messed up */
275  elog(FATAL, "no free slots in PMChildFlags array");
276  return 0; /* keep compiler quiet */
277 }
#define FATAL
Definition: elog.h:41
#define elog(elevel,...)
Definition: elog.h:225
static bool * PMChildInUse
Definition: pmsignal.c:93
static int num_child_inuse
Definition: pmsignal.c:91
static int next_child_inuse
Definition: pmsignal.c:92
NON_EXEC_STATIC volatile PMSignalData * PMSignalState
Definition: pmsignal.c:84
#define PM_CHILD_ASSIGNED
Definition: pmsignal.c:67
sig_atomic_t PMChildFlags[FLEXIBLE_ARRAY_MEMBER]
Definition: pmsignal.c:80

References elog, FATAL, next_child_inuse, num_child_inuse, PM_CHILD_ASSIGNED, PMSignalData::PMChildFlags, PMChildInUse, and PMSignalState.

Referenced by assign_backendlist_entry(), BackendStartup(), and StartAutovacuumWorker().

◆ CheckPostmasterSignal()

bool CheckPostmasterSignal ( PMSignalReason  reason)

Definition at line 201 of file pmsignal.c.

202 {
203  /* Careful here --- don't clear flag if we haven't seen it set */
204  if (PMSignalState->PMSignalFlags[reason])
205  {
206  PMSignalState->PMSignalFlags[reason] = false;
207  return true;
208  }
209  return false;
210 }
sig_atomic_t PMSignalFlags[NUM_PMSIGNALS]
Definition: pmsignal.c:75

References PMSignalData::PMSignalFlags, and PMSignalState.

Referenced by process_pm_pmsignal().

◆ GetQuitSignalReason()

QuitSignalReason GetQuitSignalReason ( void  )

Definition at line 232 of file pmsignal.c.

233 {
234  /* This is called in signal handlers, so be extra paranoid. */
235  if (!IsUnderPostmaster || PMSignalState == NULL)
236  return PMQUIT_NOT_SENT;
238 }
bool IsUnderPostmaster
Definition: globals.c:119
@ PMQUIT_NOT_SENT
Definition: pmsignal.h:52
QuitSignalReason sigquit_reason
Definition: pmsignal.c:77

References IsUnderPostmaster, PMQUIT_NOT_SENT, PMSignalState, and PMSignalData::sigquit_reason.

Referenced by quickdie().

◆ IsPostmasterChildWalSender()

bool IsPostmasterChildWalSender ( int  slot)

Definition at line 310 of file pmsignal.c.

311 {
312  Assert(slot > 0 && slot <= num_child_inuse);
313  slot--;
314 
316  return true;
317  else
318  return false;
319 }
#define Assert(condition)
Definition: c.h:849
#define PM_CHILD_WALSENDER
Definition: pmsignal.c:69

References Assert, num_child_inuse, PM_CHILD_WALSENDER, PMSignalData::PMChildFlags, and PMSignalState.

Referenced by CountChildren(), and SignalSomeChildren().

◆ MarkPostmasterChildInactive()

static void MarkPostmasterChildInactive ( int  code,
Datum  arg 
)
static

Definition at line 365 of file pmsignal.c.

366 {
367  int slot = MyPMChildSlot;
368 
369  Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
370  slot--;
374 }
int MyPMChildSlot
Definition: globals.c:53
#define PM_CHILD_ACTIVE
Definition: pmsignal.c:68

References Assert, MyPMChildSlot, PM_CHILD_ACTIVE, PM_CHILD_ASSIGNED, PM_CHILD_WALSENDER, PMSignalData::PMChildFlags, and PMSignalState.

Referenced by RegisterPostmasterChildActive().

◆ MarkPostmasterChildWalSender()

void MarkPostmasterChildWalSender ( void  )

Definition at line 348 of file pmsignal.c.

349 {
350  int slot = MyPMChildSlot;
351 
353 
354  Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
355  slot--;
358 }
bool am_walsender
Definition: walsender.c:115

References am_walsender, Assert, MyPMChildSlot, PM_CHILD_ACTIVE, PM_CHILD_WALSENDER, PMSignalData::PMChildFlags, and PMSignalState.

◆ PMSignalShmemInit()

void PMSignalShmemInit ( void  )

Definition at line 147 of file pmsignal.c.

148 {
149  bool found;
150 
152  ShmemInitStruct("PMSignalState", PMSignalShmemSize(), &found);
153 
154  if (!found)
155  {
156  /* initialize all flags to zeroes */
160 
161  /*
162  * Also allocate postmaster's private PMChildInUse[] array. We
163  * might've already done that in a previous shared-memory creation
164  * cycle, in which case free the old array to avoid a leak. (Do it
165  * like this to support the possibility that MaxLivePostmasterChildren
166  * changed.) In a standalone backend, we do not need this.
167  */
168  if (PostmasterContext != NULL)
169  {
170  if (PMChildInUse)
172  PMChildInUse = (bool *)
174  num_child_inuse * sizeof(bool));
175  }
176  next_child_inuse = 0;
177  }
178 }
#define unvolatize(underlying_type, expr)
Definition: c.h:1238
#define MemSet(start, val, len)
Definition: c.h:1011
void pfree(void *pointer)
Definition: mcxt.c:1521
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1215
MemoryContext PostmasterContext
Definition: mcxt.c:151
Size PMSignalShmemSize(void)
Definition: pmsignal.c:132
int MaxLivePostmasterChildren(void)
Definition: postmaster.c:3876
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:387
int num_child_flags
Definition: pmsignal.c:79

References MaxLivePostmasterChildren(), MemoryContextAllocZero(), MemSet, next_child_inuse, PMSignalData::num_child_flags, num_child_inuse, pfree(), PMChildInUse, PMSignalShmemSize(), PMSignalState, PostmasterContext, ShmemInitStruct(), and unvolatize.

Referenced by CreateOrAttachShmemStructs().

◆ PMSignalShmemSize()

Size PMSignalShmemSize ( void  )

Definition at line 132 of file pmsignal.c.

133 {
134  Size size;
135 
136  size = offsetof(PMSignalData, PMChildFlags);
138  sizeof(sig_atomic_t)));
139 
140  return size;
141 }
size_t Size
Definition: c.h:596
Size add_size(Size s1, Size s2)
Definition: shmem.c:493
Size mul_size(Size s1, Size s2)
Definition: shmem.c:510
static pg_noinline void Size size
Definition: slab.c:607

References add_size(), MaxLivePostmasterChildren(), mul_size(), and size.

Referenced by CalculateShmemSize(), and PMSignalShmemInit().

◆ PostmasterDeathSignalInit()

void PostmasterDeathSignalInit ( void  )

Definition at line 446 of file pmsignal.c.

447 {
448 #ifdef USE_POSTMASTER_DEATH_SIGNAL
449  int signum = POSTMASTER_DEATH_SIGNAL;
450 
451  /* Register our signal handler. */
452  pqsignal(signum, postmaster_death_handler);
453 
454  /* Request a signal on parent exit. */
455 #if defined(PR_SET_PDEATHSIG)
456  if (prctl(PR_SET_PDEATHSIG, signum) < 0)
457  elog(ERROR, "could not request parent death signal: %m");
458 #elif defined(PROC_PDEATHSIG_CTL)
459  if (procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum) < 0)
460  elog(ERROR, "could not request parent death signal: %m");
461 #else
462 #error "USE_POSTMASTER_DEATH_SIGNAL set, but there is no mechanism to request the signal"
463 #endif
464 
465  /*
466  * Just in case the parent was gone already and we missed it, we'd better
467  * check the slow way on the first call.
468  */
469  postmaster_possibly_dead = true;
470 #endif /* USE_POSTMASTER_DEATH_SIGNAL */
471 }
#define ERROR
Definition: elog.h:39
pqsigfunc pqsignal(int signo, pqsigfunc func)

References elog, ERROR, and pqsignal().

Referenced by InitPostmasterChild().

◆ PostmasterIsAliveInternal()

bool PostmasterIsAliveInternal ( void  )

Definition at line 385 of file pmsignal.c.

386 {
387 #ifdef USE_POSTMASTER_DEATH_SIGNAL
388  /*
389  * Reset the flag before checking, so that we don't miss a signal if
390  * postmaster dies right after the check. If postmaster was indeed dead,
391  * we'll re-arm it before returning to caller.
392  */
393  postmaster_possibly_dead = false;
394 #endif
395 
396 #ifndef WIN32
397  {
398  char c;
399  ssize_t rc;
400 
402 
403  /*
404  * In the usual case, the postmaster is still alive, and there is no
405  * data in the pipe.
406  */
407  if (rc < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))
408  return true;
409  else
410  {
411  /*
412  * Postmaster is dead, or something went wrong with the read()
413  * call.
414  */
415 
416 #ifdef USE_POSTMASTER_DEATH_SIGNAL
417  postmaster_possibly_dead = true;
418 #endif
419 
420  if (rc < 0)
421  elog(FATAL, "read on postmaster death monitoring pipe failed: %m");
422  else if (rc > 0)
423  elog(FATAL, "unexpected data in postmaster death monitoring pipe");
424 
425  return false;
426  }
427  }
428 
429 #else /* WIN32 */
430  if (WaitForSingleObject(PostmasterHandle, 0) == WAIT_TIMEOUT)
431  return true;
432  else
433  {
434 #ifdef USE_POSTMASTER_DEATH_SIGNAL
435  postmaster_possibly_dead = true;
436 #endif
437  return false;
438  }
439 #endif /* WIN32 */
440 }
#define read(a, b, c)
Definition: win32.h:13
int postmaster_alive_fds[2]
Definition: postmaster.c:453
#define POSTMASTER_FD_WATCH
Definition: postmaster.h:48
char * c
#define EWOULDBLOCK
Definition: win32_port.h:380
#define EAGAIN
Definition: win32_port.h:372

References EAGAIN, elog, EWOULDBLOCK, FATAL, postmaster_alive_fds, POSTMASTER_FD_WATCH, and read.

Referenced by WaitEventSetWaitBlock().

◆ RegisterPostmasterChildActive()

void RegisterPostmasterChildActive ( void  )

Definition at line 329 of file pmsignal.c.

330 {
331  int slot = MyPMChildSlot;
332 
333  Assert(slot > 0 && slot <= PMSignalState->num_child_flags);
334  slot--;
337 
338  /* Arrange to clean up at exit. */
340 }
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:365
static void MarkPostmasterChildInactive(int code, Datum arg)
Definition: pmsignal.c:365

References Assert, MarkPostmasterChildInactive(), MyPMChildSlot, on_shmem_exit(), PM_CHILD_ACTIVE, PM_CHILD_ASSIGNED, PMSignalData::PMChildFlags, and PMSignalState.

Referenced by InitProcess().

◆ ReleasePostmasterChildSlot()

bool ReleasePostmasterChildSlot ( int  slot)

Definition at line 287 of file pmsignal.c.

288 {
289  bool result;
290 
291  Assert(slot > 0 && slot <= num_child_inuse);
292  slot--;
293 
294  /*
295  * Note: the slot state might already be unused, because the logic in
296  * postmaster.c is such that this might get called twice when a child
297  * crashes. So we don't try to Assert anything about the state.
298  */
299  result = (PMSignalState->PMChildFlags[slot] == PM_CHILD_ASSIGNED);
301  PMChildInUse[slot] = false;
302  return result;
303 }
#define PM_CHILD_UNUSED
Definition: pmsignal.c:66

References Assert, num_child_inuse, PM_CHILD_ASSIGNED, PM_CHILD_UNUSED, PMSignalData::PMChildFlags, PMChildInUse, and PMSignalState.

Referenced by BackendStartup(), CleanupBackend(), do_start_bgworker(), and StartAutovacuumWorker().

◆ SendPostmasterSignal()

void SendPostmasterSignal ( PMSignalReason  reason)

Definition at line 184 of file pmsignal.c.

185 {
186  /* If called in a standalone backend, do nothing */
187  if (!IsUnderPostmaster)
188  return;
189  /* Atomically set the proper flag */
190  PMSignalState->PMSignalFlags[reason] = true;
191  /* Send signal to postmaster */
193 }
pid_t PostmasterPid
Definition: globals.c:105
#define kill(pid, sig)
Definition: win32_port.h:503
#define SIGUSR1
Definition: win32_port.h:180

References IsUnderPostmaster, kill, PMSignalData::PMSignalFlags, PMSignalState, PostmasterPid, and SIGUSR1.

Referenced by CheckRecoveryConsistency(), do_start_worker(), GetNewMultiXactId(), GetNewTransactionId(), PerformWalRecovery(), pg_rotate_logfile(), RegisterDynamicBackgroundWorker(), RequestXLogStreaming(), SetMultiXactIdLimit(), SetTransactionIdLimit(), and TerminateBackgroundWorker().

◆ SetQuitSignalReason()

void SetQuitSignalReason ( QuitSignalReason  reason)

Definition at line 221 of file pmsignal.c.

222 {
223  PMSignalState->sigquit_reason = reason;
224 }

References PMSignalState, and PMSignalData::sigquit_reason.

Referenced by HandleChildCrash(), and process_pm_shutdown_request().

Variable Documentation

◆ next_child_inuse

int next_child_inuse
static

Definition at line 92 of file pmsignal.c.

Referenced by AssignPostmasterChildSlot(), and PMSignalShmemInit().

◆ num_child_inuse

int num_child_inuse
static

◆ PMChildInUse

bool* PMChildInUse
static

◆ PMSignalState