#include "postgres.h"
#include <signal.h>
#include <unistd.h>
#include "commands/async.h"
#include "miscadmin.h"
#include "storage/latch.h"
#include "storage/ipc.h"
#include "storage/shmem.h"
#include "storage/sinval.h"
#include "tcop/tcopprot.h"
Go to the source code of this file.
Data Structures | |
struct | ProcSignalSlot |
Defines | |
#define | NumProcSignalSlots (MaxBackends + NUM_AUXPROCTYPES) |
Functions | |
static bool | CheckProcSignal (ProcSignalReason reason) |
static void | CleanupProcSignalState (int status, Datum arg) |
Size | ProcSignalShmemSize (void) |
void | ProcSignalShmemInit (void) |
void | ProcSignalInit (int pss_idx) |
int | SendProcSignal (pid_t pid, ProcSignalReason reason, BackendId backendId) |
void | procsignal_sigusr1_handler (SIGNAL_ARGS) |
Variables | |
static ProcSignalSlot * | ProcSignalSlots = NULL |
static volatile ProcSignalSlot * | MyProcSignalSlot = NULL |
#define NumProcSignalSlots (MaxBackends + NUM_AUXPROCTYPES) |
Definition at line 58 of file procsignal.c.
Referenced by ProcSignalInit(), ProcSignalShmemSize(), and SendProcSignal().
static bool CheckProcSignal | ( | ProcSignalReason | reason | ) | [static] |
Definition at line 230 of file procsignal.c.
References NULL, and ProcSignalSlot::pss_signalFlags.
Referenced by procsignal_sigusr1_handler().
{ volatile ProcSignalSlot *slot = MyProcSignalSlot; if (slot != NULL) { /* Careful here --- don't clear flag if we haven't seen it set */ if (slot->pss_signalFlags[reason]) { slot->pss_signalFlags[reason] = false; return true; } } return false; }
static void CleanupProcSignalState | ( | int | status, | |
Datum | arg | |||
) | [static] |
Definition at line 135 of file procsignal.c.
References Assert, DatumGetInt32, elog, LOG, MyProcPid, and ProcSignalSlot::pss_pid.
Referenced by ProcSignalInit().
{ int pss_idx = DatumGetInt32(arg); volatile ProcSignalSlot *slot; slot = &ProcSignalSlots[pss_idx - 1]; Assert(slot == MyProcSignalSlot); /* sanity check */ if (slot->pss_pid != MyProcPid) { /* * don't ERROR here. We're exiting anyway, and don't want to get into * infinite loop trying to exit */ elog(LOG, "process %d releasing ProcSignal slot %d, but it contains %d", MyProcPid, pss_idx, (int) slot->pss_pid); return; /* XXX better to zero the slot anyway? */ } slot->pss_pid = 0; }
void procsignal_sigusr1_handler | ( | SIGNAL_ARGS | ) |
Definition at line 251 of file procsignal.c.
References CheckProcSignal(), HandleCatchupInterrupt(), HandleNotifyInterrupt(), latch_sigusr1_handler(), PROCSIG_CATCHUP_INTERRUPT, PROCSIG_NOTIFY_INTERRUPT, PROCSIG_RECOVERY_CONFLICT_BUFFERPIN, PROCSIG_RECOVERY_CONFLICT_DATABASE, PROCSIG_RECOVERY_CONFLICT_LOCK, PROCSIG_RECOVERY_CONFLICT_SNAPSHOT, PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK, PROCSIG_RECOVERY_CONFLICT_TABLESPACE, and RecoveryConflictInterrupt().
Referenced by AutoVacLauncherMain(), AutoVacWorkerMain(), do_start_bgworker(), and PostgresMain().
{ int save_errno = errno; if (CheckProcSignal(PROCSIG_CATCHUP_INTERRUPT)) HandleCatchupInterrupt(); if (CheckProcSignal(PROCSIG_NOTIFY_INTERRUPT)) HandleNotifyInterrupt(); if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_DATABASE)) RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_DATABASE); if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_TABLESPACE)) RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_TABLESPACE); if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_LOCK)) RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_LOCK); if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_SNAPSHOT)) RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_SNAPSHOT); if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK)) RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK); if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN)) RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN); latch_sigusr1_handler(); errno = save_errno; }
void ProcSignalInit | ( | int | pss_idx | ) |
Definition at line 102 of file procsignal.c.
References Assert, CleanupProcSignalState(), elog, Int32GetDatum, LOG, MemSet, MyProcPid, NUM_PROCSIGNALS, NumProcSignalSlots, on_shmem_exit(), ProcSignalSlot::pss_pid, and ProcSignalSlot::pss_signalFlags.
Referenced by AuxiliaryProcessMain(), and InitPostgres().
{ volatile ProcSignalSlot *slot; Assert(pss_idx >= 1 && pss_idx <= NumProcSignalSlots); slot = &ProcSignalSlots[pss_idx - 1]; /* sanity check */ if (slot->pss_pid != 0) elog(LOG, "process %d taking over ProcSignal slot %d, but it's not empty", MyProcPid, pss_idx); /* Clear out any leftover signal reasons */ MemSet(slot->pss_signalFlags, 0, NUM_PROCSIGNALS * sizeof(sig_atomic_t)); /* Mark slot with my PID */ slot->pss_pid = MyProcPid; /* Remember slot location for CheckProcSignal */ MyProcSignalSlot = slot; /* Set up to release the slot on process exit */ on_shmem_exit(CleanupProcSignalState, Int32GetDatum(pss_idx)); }
void ProcSignalShmemInit | ( | void | ) |
Definition at line 81 of file procsignal.c.
References MemSet, ProcSignalShmemSize(), and ShmemInitStruct().
Referenced by CreateSharedMemoryAndSemaphores().
{ Size size = ProcSignalShmemSize(); bool found; ProcSignalSlots = (ProcSignalSlot *) ShmemInitStruct("ProcSignalSlots", size, &found); /* If we're first, set everything to zeroes */ if (!found) MemSet(ProcSignalSlots, 0, size); }
Size ProcSignalShmemSize | ( | void | ) |
Definition at line 71 of file procsignal.c.
References NumProcSignalSlots.
Referenced by CreateSharedMemoryAndSemaphores(), and ProcSignalShmemInit().
{ return NumProcSignalSlots * sizeof(ProcSignalSlot); }
int SendProcSignal | ( | pid_t | pid, | |
ProcSignalReason | reason, | |||
BackendId | backendId | |||
) |
Definition at line 170 of file procsignal.c.
References i, InvalidBackendId, NumProcSignalSlots, ProcSignalSlot::pss_pid, ProcSignalSlot::pss_signalFlags, and SIGUSR1.
Referenced by CancelDBBackends(), CancelVirtualTransaction(), SICleanupQueue(), and SignalBackends().
{ volatile ProcSignalSlot *slot; if (backendId != InvalidBackendId) { slot = &ProcSignalSlots[backendId - 1]; /* * Note: Since there's no locking, it's possible that the target * process detaches from shared memory and exits right after this * test, before we set the flag and send signal. And the signal slot * might even be recycled by a new process, so it's remotely possible * that we set a flag for a wrong process. That's OK, all the signals * are such that no harm is done if they're mistakenly fired. */ if (slot->pss_pid == pid) { /* Atomically set the proper flag */ slot->pss_signalFlags[reason] = true; /* Send signal */ return kill(pid, SIGUSR1); } } else { /* * BackendId not provided, so search the array using pid. We search * the array back to front so as to reduce search overhead. Passing * InvalidBackendId means that the target is most likely an auxiliary * process, which will have a slot near the end of the array. */ int i; for (i = NumProcSignalSlots - 1; i >= 0; i--) { slot = &ProcSignalSlots[i]; if (slot->pss_pid == pid) { /* the above note about race conditions applies here too */ /* Atomically set the proper flag */ slot->pss_signalFlags[reason] = true; /* Send signal */ return kill(pid, SIGUSR1); } } } errno = ESRCH; return -1; }
volatile ProcSignalSlot* MyProcSignalSlot = NULL [static] |
Definition at line 61 of file procsignal.c.
ProcSignalSlot* ProcSignalSlots = NULL [static] |
Definition at line 60 of file procsignal.c.