PostgreSQL Source Code  git master
procsignal.c File Reference
#include "postgres.h"
#include <signal.h>
#include <unistd.h>
#include "access/parallel.h"
#include "commands/async.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "port/pg_bitutils.h"
#include "replication/logicalworker.h"
#include "replication/walsender.h"
#include "storage/condition_variable.h"
#include "storage/ipc.h"
#include "storage/latch.h"
#include "storage/shmem.h"
#include "storage/sinval.h"
#include "storage/smgr.h"
#include "tcop/tcopprot.h"
#include "utils/memutils.h"
Include dependency graph for procsignal.c:

Go to the source code of this file.

Data Structures

struct  ProcSignalSlot
 
struct  ProcSignalHeader
 

Macros

#define NumProcSignalSlots   (MaxBackends + NUM_AUXILIARY_PROCS)
 
#define BARRIER_SHOULD_CHECK(flags, type)    (((flags) & (((uint32) 1) << (uint32) (type))) != 0)
 
#define BARRIER_CLEAR_BIT(flags, type)    ((flags) &= ~(((uint32) 1) << (uint32) (type)))
 

Functions

static bool CheckProcSignal (ProcSignalReason reason)
 
static void CleanupProcSignalState (int status, Datum arg)
 
static void ResetProcSignalBarrierBits (uint32 flags)
 
Size ProcSignalShmemSize (void)
 
void ProcSignalShmemInit (void)
 
void ProcSignalInit (void)
 
int SendProcSignal (pid_t pid, ProcSignalReason reason, ProcNumber procNumber)
 
uint64 EmitProcSignalBarrier (ProcSignalBarrierType type)
 
void WaitForProcSignalBarrier (uint64 generation)
 
static void HandleProcSignalBarrierInterrupt (void)
 
void ProcessProcSignalBarrier (void)
 
void procsignal_sigusr1_handler (SIGNAL_ARGS)
 

Variables

static ProcSignalHeaderProcSignal = NULL
 
static ProcSignalSlotMyProcSignalSlot = NULL
 

Macro Definition Documentation

◆ BARRIER_CLEAR_BIT

#define BARRIER_CLEAR_BIT (   flags,
  type 
)     ((flags) &= ~(((uint32) 1) << (uint32) (type)))

Definition at line 96 of file procsignal.c.

◆ BARRIER_SHOULD_CHECK

#define BARRIER_SHOULD_CHECK (   flags,
  type 
)     (((flags) & (((uint32) 1) << (uint32) (type))) != 0)

Definition at line 92 of file procsignal.c.

◆ NumProcSignalSlots

#define NumProcSignalSlots   (MaxBackends + NUM_AUXILIARY_PROCS)

Definition at line 89 of file procsignal.c.

Function Documentation

◆ CheckProcSignal()

static bool CheckProcSignal ( ProcSignalReason  reason)
static

Definition at line 614 of file procsignal.c.

615 {
616  volatile ProcSignalSlot *slot = MyProcSignalSlot;
617 
618  if (slot != NULL)
619  {
620  /* Careful here --- don't clear flag if we haven't seen it set */
621  if (slot->pss_signalFlags[reason])
622  {
623  slot->pss_signalFlags[reason] = false;
624  return true;
625  }
626  }
627 
628  return false;
629 }
static ProcSignalSlot * MyProcSignalSlot
Definition: procsignal.c:100
volatile sig_atomic_t pss_signalFlags[NUM_PROCSIGNALS]
Definition: procsignal.c:66

References MyProcSignalSlot, and ProcSignalSlot::pss_signalFlags.

Referenced by procsignal_sigusr1_handler().

◆ CleanupProcSignalState()

static void CleanupProcSignalState ( int  status,
Datum  arg 
)
static

Definition at line 211 of file procsignal.c.

212 {
214 
215  /*
216  * Clear MyProcSignalSlot, so that a SIGUSR1 received after this point
217  * won't try to access it after it's no longer ours (and perhaps even
218  * after we've unmapped the shared memory segment).
219  */
220  Assert(MyProcSignalSlot != NULL);
221  MyProcSignalSlot = NULL;
222 
223  /* sanity check */
224  if (slot->pss_pid != MyProcPid)
225  {
226  /*
227  * don't ERROR here. We're exiting anyway, and don't want to get into
228  * infinite loop trying to exit
229  */
230  elog(LOG, "process %d releasing ProcSignal slot %d, but it contains %d",
231  MyProcPid, (int) (slot - ProcSignal->psh_slot), (int) slot->pss_pid);
232  return; /* XXX better to zero the slot anyway? */
233  }
234 
235  /*
236  * Make this slot look like it's absorbed all possible barriers, so that
237  * no barrier waits block on it.
238  */
241 
242  slot->pss_pid = 0;
243 }
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:480
#define Assert(condition)
Definition: c.h:858
#define PG_UINT64_MAX
Definition: c.h:593
void ConditionVariableBroadcast(ConditionVariable *cv)
#define LOG
Definition: elog.h:31
#define elog(elevel,...)
Definition: elog.h:224
int MyProcPid
Definition: globals.c:45
static ProcSignalHeader * ProcSignal
Definition: procsignal.c:99
ProcSignalSlot psh_slot[FLEXIBLE_ARRAY_MEMBER]
Definition: procsignal.c:81
ConditionVariable pss_barrierCV
Definition: procsignal.c:69
pg_atomic_uint64 pss_barrierGeneration
Definition: procsignal.c:67
volatile pid_t pss_pid
Definition: procsignal.c:65

References Assert, ConditionVariableBroadcast(), elog, LOG, MyProcPid, MyProcSignalSlot, pg_atomic_write_u64(), PG_UINT64_MAX, ProcSignal, ProcSignalHeader::psh_slot, ProcSignalSlot::pss_barrierCV, ProcSignalSlot::pss_barrierGeneration, and ProcSignalSlot::pss_pid.

Referenced by ProcSignalInit().

◆ EmitProcSignalBarrier()

uint64 EmitProcSignalBarrier ( ProcSignalBarrierType  type)

Definition at line 329 of file procsignal.c.

330 {
331  uint32 flagbit = 1 << (uint32) type;
332  uint64 generation;
333 
334  /*
335  * Set all the flags.
336  *
337  * Note that pg_atomic_fetch_or_u32 has full barrier semantics, so this is
338  * totally ordered with respect to anything the caller did before, and
339  * anything that we do afterwards. (This is also true of the later call to
340  * pg_atomic_add_fetch_u64.)
341  */
342  for (int i = 0; i < NumProcSignalSlots; i++)
343  {
344  volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i];
345 
347  }
348 
349  /*
350  * Increment the generation counter.
351  */
352  generation =
354 
355  /*
356  * Signal all the processes, so that they update their advertised barrier
357  * generation.
358  *
359  * Concurrency is not a problem here. Backends that have exited don't
360  * matter, and new backends that have joined since we entered this
361  * function must already have current state, since the caller is
362  * responsible for making sure that the relevant state is entirely visible
363  * before calling this function in the first place. We still have to wake
364  * them up - because we can't distinguish between such backends and older
365  * backends that need to update state - but they won't actually need to
366  * change any state.
367  */
368  for (int i = NumProcSignalSlots - 1; i >= 0; i--)
369  {
370  volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i];
371  pid_t pid = slot->pss_pid;
372 
373  if (pid != 0)
374  {
375  /* see SendProcSignal for details */
376  slot->pss_signalFlags[PROCSIG_BARRIER] = true;
377  kill(pid, SIGUSR1);
378  }
379  }
380 
381  return generation;
382 }
static uint32 pg_atomic_fetch_or_u32(volatile pg_atomic_uint32 *ptr, uint32 or_)
Definition: atomics.h:405
static uint64 pg_atomic_add_fetch_u64(volatile pg_atomic_uint64 *ptr, int64 add_)
Definition: atomics.h:555
unsigned int uint32
Definition: c.h:506
int i
Definition: isn.c:73
#define NumProcSignalSlots
Definition: procsignal.c:89
@ PROCSIG_BARRIER
Definition: procsignal.h:36
pg_atomic_uint64 psh_barrierGeneration
Definition: procsignal.c:80
pg_atomic_uint32 pss_barrierCheckMask
Definition: procsignal.c:68
const char * type
#define kill(pid, sig)
Definition: win32_port.h:485
#define SIGUSR1
Definition: win32_port.h:180

References i, kill, NumProcSignalSlots, pg_atomic_add_fetch_u64(), pg_atomic_fetch_or_u32(), PROCSIG_BARRIER, ProcSignal, ProcSignalHeader::psh_barrierGeneration, ProcSignalHeader::psh_slot, ProcSignalSlot::pss_barrierCheckMask, ProcSignalSlot::pss_pid, ProcSignalSlot::pss_signalFlags, SIGUSR1, and type.

Referenced by dbase_redo(), dropdb(), DropTableSpace(), movedb(), and tblspc_redo().

◆ HandleProcSignalBarrierInterrupt()

static void HandleProcSignalBarrierInterrupt ( void  )
static

Definition at line 448 of file procsignal.c.

449 {
450  InterruptPending = true;
452  /* latch will be set by procsignal_sigusr1_handler */
453 }
volatile sig_atomic_t ProcSignalBarrierPending
Definition: globals.c:38
volatile sig_atomic_t InterruptPending
Definition: globals.c:30

References InterruptPending, and ProcSignalBarrierPending.

Referenced by procsignal_sigusr1_handler().

◆ ProcessProcSignalBarrier()

void ProcessProcSignalBarrier ( void  )

Definition at line 464 of file procsignal.c.

465 {
466  uint64 local_gen;
467  uint64 shared_gen;
468  volatile uint32 flags;
469 
471 
472  /* Exit quickly if there's no work to do. */
474  return;
475  ProcSignalBarrierPending = false;
476 
477  /*
478  * It's not unlikely to process multiple barriers at once, before the
479  * signals for all the barriers have arrived. To avoid unnecessary work in
480  * response to subsequent signals, exit early if we already have processed
481  * all of them.
482  */
485 
486  Assert(local_gen <= shared_gen);
487 
488  if (local_gen == shared_gen)
489  return;
490 
491  /*
492  * Get and clear the flags that are set for this backend. Note that
493  * pg_atomic_exchange_u32 is a full barrier, so we're guaranteed that the
494  * read of the barrier generation above happens before we atomically
495  * extract the flags, and that any subsequent state changes happen
496  * afterward.
497  *
498  * NB: In order to avoid race conditions, we must zero
499  * pss_barrierCheckMask first and only afterwards try to do barrier
500  * processing. If we did it in the other order, someone could send us
501  * another barrier of some type right after we called the
502  * barrier-processing function but before we cleared the bit. We would
503  * have no way of knowing that the bit needs to stay set in that case, so
504  * the need to call the barrier-processing function again would just get
505  * forgotten. So instead, we tentatively clear all the bits and then put
506  * back any for which we don't manage to successfully absorb the barrier.
507  */
509 
510  /*
511  * If there are no flags set, then we can skip doing any real work.
512  * Otherwise, establish a PG_TRY block, so that we don't lose track of
513  * which types of barrier processing are needed if an ERROR occurs.
514  */
515  if (flags != 0)
516  {
517  bool success = true;
518 
519  PG_TRY();
520  {
521  /*
522  * Process each type of barrier. The barrier-processing functions
523  * should normally return true, but may return false if the
524  * barrier can't be absorbed at the current time. This should be
525  * rare, because it's pretty expensive. Every single
526  * CHECK_FOR_INTERRUPTS() will return here until we manage to
527  * absorb the barrier, and that cost will add up in a hurry.
528  *
529  * NB: It ought to be OK to call the barrier-processing functions
530  * unconditionally, but it's more efficient to call only the ones
531  * that might need us to do something based on the flags.
532  */
533  while (flags != 0)
534  {
536  bool processed = true;
537 
539  switch (type)
540  {
542  processed = ProcessBarrierSmgrRelease();
543  break;
544  }
545 
546  /*
547  * To avoid an infinite loop, we must always unset the bit in
548  * flags.
549  */
550  BARRIER_CLEAR_BIT(flags, type);
551 
552  /*
553  * If we failed to process the barrier, reset the shared bit
554  * so we try again later, and set a flag so that we don't bump
555  * our generation.
556  */
557  if (!processed)
558  {
560  success = false;
561  }
562  }
563  }
564  PG_CATCH();
565  {
566  /*
567  * If an ERROR occurred, we'll need to try again later to handle
568  * that barrier type and any others that haven't been handled yet
569  * or weren't successfully absorbed.
570  */
572  PG_RE_THROW();
573  }
574  PG_END_TRY();
575 
576  /*
577  * If some barrier types were not successfully absorbed, we will have
578  * to try again later.
579  */
580  if (!success)
581  return;
582  }
583 
584  /*
585  * State changes related to all types of barriers that might have been
586  * emitted have now been handled, so we can update our notion of the
587  * generation to the one we observed before beginning the updates. If
588  * things have changed further, it'll get fixed up when this function is
589  * next called.
590  */
593 }
static uint32 pg_atomic_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 newval)
Definition: atomics.h:325
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
Definition: atomics.h:462
#define PG_RE_THROW()
Definition: elog.h:411
#define PG_TRY(...)
Definition: elog.h:370
#define PG_END_TRY(...)
Definition: elog.h:395
#define PG_CATCH(...)
Definition: elog.h:380
static bool success
Definition: initdb.c:186
static int pg_rightmost_one_pos32(uint32 word)
Definition: pg_bitutils.h:111
static void ResetProcSignalBarrierBits(uint32 flags)
Definition: procsignal.c:601
#define BARRIER_CLEAR_BIT(flags, type)
Definition: procsignal.c:96
ProcSignalBarrierType
Definition: procsignal.h:55
@ PROCSIGNAL_BARRIER_SMGRRELEASE
Definition: procsignal.h:56
bool ProcessBarrierSmgrRelease(void)
Definition: smgr.c:817

References Assert, BARRIER_CLEAR_BIT, ConditionVariableBroadcast(), MyProcSignalSlot, pg_atomic_exchange_u32(), pg_atomic_read_u64(), pg_atomic_write_u64(), PG_CATCH, PG_END_TRY, PG_RE_THROW, pg_rightmost_one_pos32(), PG_TRY, ProcessBarrierSmgrRelease(), ProcSignal, PROCSIGNAL_BARRIER_SMGRRELEASE, ProcSignalBarrierPending, ProcSignalHeader::psh_barrierGeneration, ProcSignalSlot::pss_barrierCheckMask, ProcSignalSlot::pss_barrierCV, ProcSignalSlot::pss_barrierGeneration, ResetProcSignalBarrierBits(), success, and type.

Referenced by BufferSync(), CheckpointWriteDelay(), HandleAutoVacLauncherInterrupts(), HandleCheckpointerInterrupts(), HandleMainLoopInterrupts(), HandlePgArchInterrupts(), HandleStartupProcInterrupts(), HandleWalSummarizerInterrupts(), and ProcessInterrupts().

◆ procsignal_sigusr1_handler()

void procsignal_sigusr1_handler ( SIGNAL_ARGS  )

Definition at line 635 of file procsignal.c.

636 {
639 
642 
645 
648 
651 
654 
657 
660 
663 
666 
669 
672 
675 
678 
679  SetLatch(MyLatch);
680 }
void HandleParallelApplyMessageInterrupt(void)
void HandleNotifyInterrupt(void)
Definition: async.c:1804
void HandleParallelMessageInterrupt(void)
Definition: parallel.c:1016
struct Latch * MyLatch
Definition: globals.c:60
void SetLatch(Latch *latch)
Definition: latch.c:632
void HandleLogMemoryContextInterrupt(void)
Definition: mcxt.c:1271
void HandleRecoveryConflictInterrupt(ProcSignalReason reason)
Definition: postgres.c:3035
static bool CheckProcSignal(ProcSignalReason reason)
Definition: procsignal.c:614
static void HandleProcSignalBarrierInterrupt(void)
Definition: procsignal.c:448
@ PROCSIG_PARALLEL_MESSAGE
Definition: procsignal.h:34
@ PROCSIG_RECOVERY_CONFLICT_BUFFERPIN
Definition: procsignal.h:47
@ PROCSIG_CATCHUP_INTERRUPT
Definition: procsignal.h:32
@ PROCSIG_RECOVERY_CONFLICT_LOCK
Definition: procsignal.h:44
@ PROCSIG_LOG_MEMORY_CONTEXT
Definition: procsignal.h:37
@ PROCSIG_RECOVERY_CONFLICT_LOGICALSLOT
Definition: procsignal.h:46
@ PROCSIG_RECOVERY_CONFLICT_DATABASE
Definition: procsignal.h:42
@ PROCSIG_WALSND_INIT_STOPPING
Definition: procsignal.h:35
@ PROCSIG_PARALLEL_APPLY_MESSAGE
Definition: procsignal.h:38
@ PROCSIG_RECOVERY_CONFLICT_SNAPSHOT
Definition: procsignal.h:45
@ PROCSIG_NOTIFY_INTERRUPT
Definition: procsignal.h:33
@ PROCSIG_RECOVERY_CONFLICT_TABLESPACE
Definition: procsignal.h:43
@ PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK
Definition: procsignal.h:48
void HandleCatchupInterrupt(void)
Definition: sinval.c:154
void HandleWalSndInitStopping(void)
Definition: walsender.c:3560

References CheckProcSignal(), HandleCatchupInterrupt(), HandleLogMemoryContextInterrupt(), HandleNotifyInterrupt(), HandleParallelApplyMessageInterrupt(), HandleParallelMessageInterrupt(), HandleProcSignalBarrierInterrupt(), HandleRecoveryConflictInterrupt(), HandleWalSndInitStopping(), MyLatch, PROCSIG_BARRIER, PROCSIG_CATCHUP_INTERRUPT, PROCSIG_LOG_MEMORY_CONTEXT, PROCSIG_NOTIFY_INTERRUPT, PROCSIG_PARALLEL_APPLY_MESSAGE, PROCSIG_PARALLEL_MESSAGE, PROCSIG_RECOVERY_CONFLICT_BUFFERPIN, PROCSIG_RECOVERY_CONFLICT_DATABASE, PROCSIG_RECOVERY_CONFLICT_LOCK, PROCSIG_RECOVERY_CONFLICT_LOGICALSLOT, PROCSIG_RECOVERY_CONFLICT_SNAPSHOT, PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK, PROCSIG_RECOVERY_CONFLICT_TABLESPACE, PROCSIG_WALSND_INIT_STOPPING, and SetLatch().

Referenced by autoprewarm_main(), AutoVacWorkerMain(), BackgroundWorkerMain(), BackgroundWriterMain(), CheckpointerMain(), PgArchiverMain(), PostgresMain(), ReplSlotSyncWorkerMain(), StartupProcessMain(), WalReceiverMain(), WalSndSignals(), WalSummarizerMain(), and WalWriterMain().

◆ ProcSignalInit()

void ProcSignalInit ( void  )

Definition at line 158 of file procsignal.c.

159 {
160  ProcSignalSlot *slot;
161  uint64 barrier_generation;
162 
163  if (MyProcNumber < 0)
164  elog(ERROR, "MyProcNumber not set");
166  elog(ERROR, "unexpected MyProcNumber %d in ProcSignalInit (max %d)", MyProcNumber, NumProcSignalSlots);
167  slot = &ProcSignal->psh_slot[MyProcNumber];
168 
169  /* sanity check */
170  if (slot->pss_pid != 0)
171  elog(LOG, "process %d taking over ProcSignal slot %d, but it's not empty",
173 
174  /* Clear out any leftover signal reasons */
175  MemSet(slot->pss_signalFlags, 0, NUM_PROCSIGNALS * sizeof(sig_atomic_t));
176 
177  /*
178  * Initialize barrier state. Since we're a brand-new process, there
179  * shouldn't be any leftover backend-private state that needs to be
180  * updated. Therefore, we can broadcast the latest barrier generation and
181  * disregard any previously-set check bits.
182  *
183  * NB: This only works if this initialization happens early enough in the
184  * startup sequence that we haven't yet cached any state that might need
185  * to be invalidated. That's also why we have a memory barrier here, to be
186  * sure that any later reads of memory happen strictly after this.
187  */
189  barrier_generation =
191  pg_atomic_write_u64(&slot->pss_barrierGeneration, barrier_generation);
193 
194  /* Mark slot with my PID */
195  slot->pss_pid = MyProcPid;
196 
197  /* Remember slot location for CheckProcSignal */
198  MyProcSignalSlot = slot;
199 
200  /* Set up to release the slot on process exit */
202 }
#define pg_memory_barrier()
Definition: atomics.h:138
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:271
#define MemSet(start, val, len)
Definition: c.h:1020
#define ERROR
Definition: elog.h:39
ProcNumber MyProcNumber
Definition: globals.c:87
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:365
uintptr_t Datum
Definition: postgres.h:64
static void CleanupProcSignalState(int status, Datum arg)
Definition: procsignal.c:211
@ NUM_PROCSIGNALS
Definition: procsignal.h:51

References CleanupProcSignalState(), elog, ERROR, LOG, MemSet, MyProcNumber, MyProcPid, MyProcSignalSlot, NUM_PROCSIGNALS, NumProcSignalSlots, on_shmem_exit(), pg_atomic_read_u64(), pg_atomic_write_u32(), pg_atomic_write_u64(), pg_memory_barrier, ProcSignal, ProcSignalHeader::psh_barrierGeneration, ProcSignalHeader::psh_slot, ProcSignalSlot::pss_barrierCheckMask, ProcSignalSlot::pss_barrierGeneration, ProcSignalSlot::pss_pid, and ProcSignalSlot::pss_signalFlags.

Referenced by AuxiliaryProcessMainCommon(), and InitPostgres().

◆ ProcSignalShmemInit()

void ProcSignalShmemInit ( void  )

Definition at line 125 of file procsignal.c.

126 {
128  bool found;
129 
131  ShmemInitStruct("ProcSignal", size, &found);
132 
133  /* If we're first, initialize. */
134  if (!found)
135  {
136  int i;
137 
139 
140  for (i = 0; i < NumProcSignalSlots; ++i)
141  {
142  ProcSignalSlot *slot = &ProcSignal->psh_slot[i];
143 
144  slot->pss_pid = 0;
145  MemSet(slot->pss_signalFlags, 0, sizeof(slot->pss_signalFlags));
149  }
150  }
151 }
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:216
static void pg_atomic_init_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:448
size_t Size
Definition: c.h:605
void ConditionVariableInit(ConditionVariable *cv)
Size ProcSignalShmemSize(void)
Definition: procsignal.c:111
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:387
static pg_noinline void Size size
Definition: slab.c:607

References ConditionVariableInit(), i, MemSet, NumProcSignalSlots, pg_atomic_init_u32(), pg_atomic_init_u64(), PG_UINT64_MAX, ProcSignal, ProcSignalShmemSize(), ProcSignalHeader::psh_barrierGeneration, ProcSignalHeader::psh_slot, ProcSignalSlot::pss_barrierCheckMask, ProcSignalSlot::pss_barrierCV, ProcSignalSlot::pss_barrierGeneration, ProcSignalSlot::pss_pid, ProcSignalSlot::pss_signalFlags, ShmemInitStruct(), and size.

Referenced by CreateOrAttachShmemStructs().

◆ ProcSignalShmemSize()

Size ProcSignalShmemSize ( void  )

Definition at line 111 of file procsignal.c.

112 {
113  Size size;
114 
116  size = add_size(size, offsetof(ProcSignalHeader, psh_slot));
117  return size;
118 }
Size add_size(Size s1, Size s2)
Definition: shmem.c:493
Size mul_size(Size s1, Size s2)
Definition: shmem.c:510

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

Referenced by CalculateShmemSize(), and ProcSignalShmemInit().

◆ ResetProcSignalBarrierBits()

static void ResetProcSignalBarrierBits ( uint32  flags)
static

◆ SendProcSignal()

int SendProcSignal ( pid_t  pid,
ProcSignalReason  reason,
ProcNumber  procNumber 
)

Definition at line 257 of file procsignal.c.

258 {
259  volatile ProcSignalSlot *slot;
260 
261  if (procNumber != INVALID_PROC_NUMBER)
262  {
263  slot = &ProcSignal->psh_slot[procNumber];
264 
265  /*
266  * Note: Since there's no locking, it's possible that the target
267  * process detaches from shared memory and exits right after this
268  * test, before we set the flag and send signal. And the signal slot
269  * might even be recycled by a new process, so it's remotely possible
270  * that we set a flag for a wrong process. That's OK, all the signals
271  * are such that no harm is done if they're mistakenly fired.
272  */
273  if (slot->pss_pid == pid)
274  {
275  /* Atomically set the proper flag */
276  slot->pss_signalFlags[reason] = true;
277  /* Send signal */
278  return kill(pid, SIGUSR1);
279  }
280  }
281  else
282  {
283  /*
284  * Pronumber not provided, so search the array using pid. We search
285  * the array back to front so as to reduce search overhead. Passing
286  * INVALID_PROC_NUMBER means that the target is most likely an
287  * auxiliary process, which will have a slot near the end of the
288  * array.
289  */
290  int i;
291 
292  for (i = NumProcSignalSlots - 1; i >= 0; i--)
293  {
294  slot = &ProcSignal->psh_slot[i];
295 
296  if (slot->pss_pid == pid)
297  {
298  /* the above note about race conditions applies here too */
299 
300  /* Atomically set the proper flag */
301  slot->pss_signalFlags[reason] = true;
302  /* Send signal */
303  return kill(pid, SIGUSR1);
304  }
305  }
306  }
307 
308  errno = ESRCH;
309  return -1;
310 }
#define INVALID_PROC_NUMBER
Definition: procnumber.h:26

References i, INVALID_PROC_NUMBER, kill, NumProcSignalSlots, ProcSignal, ProcSignalHeader::psh_slot, ProcSignalSlot::pss_pid, ProcSignalSlot::pss_signalFlags, and SIGUSR1.

Referenced by CancelDBBackends(), InvalidatePossiblyObsoleteSlot(), mq_putmessage(), pa_shutdown(), ParallelWorkerShutdown(), pg_log_backend_memory_contexts(), SICleanupQueue(), SignalBackends(), SignalVirtualTransaction(), and WalSndInitStopping().

◆ WaitForProcSignalBarrier()

void WaitForProcSignalBarrier ( uint64  generation)

Definition at line 389 of file procsignal.c.

390 {
392 
393  elog(DEBUG1,
394  "waiting for all backends to process ProcSignalBarrier generation "
396  generation);
397 
398  for (int i = NumProcSignalSlots - 1; i >= 0; i--)
399  {
400  ProcSignalSlot *slot = &ProcSignal->psh_slot[i];
401  uint64 oldval;
402 
403  /*
404  * It's important that we check only pss_barrierGeneration here and
405  * not pss_barrierCheckMask. Bits in pss_barrierCheckMask get cleared
406  * before the barrier is actually absorbed, but pss_barrierGeneration
407  * is updated only afterward.
408  */
409  oldval = pg_atomic_read_u64(&slot->pss_barrierGeneration);
410  while (oldval < generation)
411  {
413  5000,
414  WAIT_EVENT_PROC_SIGNAL_BARRIER))
415  ereport(LOG,
416  (errmsg("still waiting for backend with PID %d to accept ProcSignalBarrier",
417  (int) slot->pss_pid)));
418  oldval = pg_atomic_read_u64(&slot->pss_barrierGeneration);
419  }
421  }
422 
423  elog(DEBUG1,
424  "finished waiting for all backends to process ProcSignalBarrier generation "
426  generation);
427 
428  /*
429  * The caller is probably calling this function because it wants to read
430  * the shared state or perform further writes to shared state once all
431  * backends are known to have absorbed the barrier. However, the read of
432  * pss_barrierGeneration was performed unlocked; insert a memory barrier
433  * to separate it from whatever follows.
434  */
436 }
#define UINT64_FORMAT
Definition: c.h:549
bool ConditionVariableCancelSleep(void)
bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, uint32 wait_event_info)
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define DEBUG1
Definition: elog.h:30
#define ereport(elevel,...)
Definition: elog.h:149

References Assert, ConditionVariableCancelSleep(), ConditionVariableTimedSleep(), DEBUG1, elog, ereport, errmsg(), i, LOG, NumProcSignalSlots, pg_atomic_read_u64(), pg_memory_barrier, ProcSignal, ProcSignalHeader::psh_barrierGeneration, ProcSignalHeader::psh_slot, ProcSignalSlot::pss_barrierCV, ProcSignalSlot::pss_barrierGeneration, ProcSignalSlot::pss_pid, and UINT64_FORMAT.

Referenced by dbase_redo(), dropdb(), DropTableSpace(), movedb(), and tblspc_redo().

Variable Documentation

◆ MyProcSignalSlot

◆ ProcSignal