PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
bgworker.c File Reference
#include "postgres.h"
#include <unistd.h>
#include "libpq/pqsignal.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "port/atomics.h"
#include "postmaster/bgworker_internals.h"
#include "postmaster/postmaster.h"
#include "replication/logicallauncher.h"
#include "storage/dsm.h"
#include "storage/ipc.h"
#include "storage/latch.h"
#include "storage/lwlock.h"
#include "storage/pg_shmem.h"
#include "storage/pmsignal.h"
#include "storage/proc.h"
#include "storage/procsignal.h"
#include "storage/shmem.h"
#include "tcop/tcopprot.h"
#include "utils/ascii.h"
#include "utils/ps_status.h"
#include "utils/timeout.h"
Include dependency graph for bgworker.c:

Go to the source code of this file.

Data Structures

struct  BackgroundWorkerSlot
 
struct  BackgroundWorkerArray
 
struct  BackgroundWorkerHandle
 

Typedefs

typedef struct BackgroundWorkerSlot BackgroundWorkerSlot
 
typedef struct
BackgroundWorkerArray 
BackgroundWorkerArray
 

Functions

Size BackgroundWorkerShmemSize (void)
 
void BackgroundWorkerShmemInit (void)
 
static RegisteredBgWorkerFindRegisteredWorkerBySlotNumber (int slotno)
 
void BackgroundWorkerStateChange (void)
 
void ForgetBackgroundWorker (slist_mutable_iter *cur)
 
void ReportBackgroundWorkerPID (RegisteredBgWorker *rw)
 
void ReportBackgroundWorkerExit (slist_mutable_iter *cur)
 
void BackgroundWorkerStopNotifications (pid_t pid)
 
void ResetBackgroundWorkerCrashTimes (void)
 
static bool SanityCheckBackgroundWorker (BackgroundWorker *worker, int elevel)
 
static void bgworker_quickdie (SIGNAL_ARGS)
 
static void bgworker_die (SIGNAL_ARGS)
 
static void bgworker_sigusr1_handler (SIGNAL_ARGS)
 
void StartBackgroundWorker (void)
 
void RegisterBackgroundWorker (BackgroundWorker *worker)
 
bool RegisterDynamicBackgroundWorker (BackgroundWorker *worker, BackgroundWorkerHandle **handle)
 
BgwHandleStatus GetBackgroundWorkerPid (BackgroundWorkerHandle *handle, pid_t *pidp)
 
BgwHandleStatus WaitForBackgroundWorkerStartup (BackgroundWorkerHandle *handle, pid_t *pidp)
 
BgwHandleStatus WaitForBackgroundWorkerShutdown (BackgroundWorkerHandle *handle)
 
void TerminateBackgroundWorker (BackgroundWorkerHandle *handle)
 

Variables

slist_head BackgroundWorkerList = SLIST_STATIC_INIT(BackgroundWorkerList)
 
static BackgroundWorkerArrayBackgroundWorkerData
 
static const bgworker_main_type InternalBGWorkers []
 

Typedef Documentation

Function Documentation

void BackgroundWorkerShmemInit ( void  )

Definition at line 140 of file bgworker.c.

References Assert, BackgroundWorkerShmemSize(), BackgroundWorker::bgw_notify_pid, slist_iter::cur, BackgroundWorkerSlot::generation, BackgroundWorkerSlot::in_use, InvalidPid, IsUnderPostmaster, max_worker_processes, BackgroundWorkerArray::parallel_register_count, BackgroundWorkerArray::parallel_terminate_count, BackgroundWorkerSlot::pid, RegisteredBgWorker::rw_shmem_slot, RegisteredBgWorker::rw_worker, ShmemInitStruct(), slist_container, slist_foreach, BackgroundWorkerArray::slot, BackgroundWorkerSlot::terminate, BackgroundWorkerArray::total_slots, and BackgroundWorkerSlot::worker.

Referenced by CreateSharedMemoryAndSemaphores().

141 {
142  bool found;
143 
144  BackgroundWorkerData = ShmemInitStruct("Background Worker Data",
146  &found);
147  if (!IsUnderPostmaster)
148  {
149  slist_iter siter;
150  int slotno = 0;
151 
155 
156  /*
157  * Copy contents of worker list into shared memory. Record the shared
158  * memory slot assigned to each worker. This ensures a 1-to-1
159  * correspondence between the postmaster's private list and the array
160  * in shared memory.
161  */
163  {
165  RegisteredBgWorker *rw;
166 
167  rw = slist_container(RegisteredBgWorker, rw_lnode, siter.cur);
168  Assert(slotno < max_worker_processes);
169  slot->in_use = true;
170  slot->terminate = false;
171  slot->pid = InvalidPid;
172  slot->generation = 0;
173  rw->rw_shmem_slot = slotno;
174  rw->rw_worker.bgw_notify_pid = 0; /* might be reinit after crash */
175  memcpy(&slot->worker, &rw->rw_worker, sizeof(BackgroundWorker));
176  ++slotno;
177  }
178 
179  /*
180  * Mark any remaining slots as not in use.
181  */
182  while (slotno < max_worker_processes)
183  {
185 
186  slot->in_use = false;
187  ++slotno;
188  }
189  }
190  else
191  Assert(found);
192 }
slist_node * cur
Definition: ilist.h:226
static BackgroundWorkerArray * BackgroundWorkerData
Definition: bgworker.c:109
Size BackgroundWorkerShmemSize(void)
Definition: bgworker.c:124
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:372
slist_head BackgroundWorkerList
Definition: bgworker.c:41
uint32 parallel_register_count
Definition: bgworker.c:98
bool IsUnderPostmaster
Definition: globals.c:100
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
#define Assert(condition)
Definition: c.h:675
BackgroundWorker worker
Definition: bgworker.c:81
#define slist_foreach(iter, lhead)
Definition: ilist.h:700
uint32 parallel_terminate_count
Definition: bgworker.c:99
pid_t bgw_notify_pid
Definition: bgworker.h:99
int max_worker_processes
Definition: globals.c:124
BackgroundWorker rw_worker
BackgroundWorkerSlot slot[FLEXIBLE_ARRAY_MEMBER]
Definition: bgworker.c:100
#define InvalidPid
Definition: miscadmin.h:31
Size BackgroundWorkerShmemSize ( void  )

Definition at line 124 of file bgworker.c.

References add_size(), max_worker_processes, mul_size(), and offsetof.

Referenced by BackgroundWorkerShmemInit(), and CreateSharedMemoryAndSemaphores().

125 {
126  Size size;
127 
128  /* Array of workers is variably sized. */
129  size = offsetof(BackgroundWorkerArray, slot);
131  sizeof(BackgroundWorkerSlot)));
132 
133  return size;
134 }
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
size_t Size
Definition: c.h:356
int max_worker_processes
Definition: globals.c:124
#define offsetof(type, field)
Definition: c.h:555
void BackgroundWorkerStateChange ( void  )

Definition at line 222 of file bgworker.c.

References ascii_safe_strlcpy(), BackgroundWorker::bgw_extra, BGW_EXTRALEN, BackgroundWorker::bgw_flags, BackgroundWorker::bgw_function_name, BackgroundWorker::bgw_library_name, BackgroundWorker::bgw_main, BackgroundWorker::bgw_main_arg, BGW_MAXLEN, BackgroundWorker::bgw_name, BackgroundWorker::bgw_notify_pid, BackgroundWorker::bgw_restart_time, BackgroundWorker::bgw_start_time, BGWORKER_CLASS_PARALLEL, DEBUG1, elog, ereport, errcode(), errmsg(), FindRegisteredWorkerBySlotNumber(), BackgroundWorkerSlot::in_use, LOG, malloc, max_worker_processes, NULL, BackgroundWorkerArray::parallel_terminate_count, pg_memory_barrier, pg_read_barrier, BackgroundWorkerSlot::pid, PostmasterMarkPIDForWorkerNotify(), ReportBackgroundWorkerPID(), RegisteredBgWorker::rw_backend, RegisteredBgWorker::rw_child_slot, RegisteredBgWorker::rw_crashed_at, RegisteredBgWorker::rw_lnode, RegisteredBgWorker::rw_pid, RegisteredBgWorker::rw_shmem_slot, RegisteredBgWorker::rw_terminate, RegisteredBgWorker::rw_worker, SIGUSR1, slist_push_head(), BackgroundWorkerArray::slot, BackgroundWorkerSlot::terminate, BackgroundWorkerArray::total_slots, and BackgroundWorkerSlot::worker.

Referenced by sigusr1_handler().

223 {
224  int slotno;
225 
226  /*
227  * The total number of slots stored in shared memory should match our
228  * notion of max_worker_processes. If it does not, something is very
229  * wrong. Further down, we always refer to this value as
230  * max_worker_processes, in case shared memory gets corrupted while we're
231  * looping.
232  */
234  {
235  elog(LOG,
236  "inconsistent background worker state (max_worker_processes=%d, total_slots=%d",
239  return;
240  }
241 
242  /*
243  * Iterate through slots, looking for newly-registered workers or workers
244  * who must die.
245  */
246  for (slotno = 0; slotno < max_worker_processes; ++slotno)
247  {
249  RegisteredBgWorker *rw;
250 
251  if (!slot->in_use)
252  continue;
253 
254  /*
255  * Make sure we don't see the in_use flag before the updated slot
256  * contents.
257  */
258  pg_read_barrier();
259 
260  /* See whether we already know about this worker. */
262  if (rw != NULL)
263  {
264  /*
265  * In general, the worker data can't change after it's initially
266  * registered. However, someone can set the terminate flag.
267  */
268  if (slot->terminate && !rw->rw_terminate)
269  {
270  rw->rw_terminate = true;
271  if (rw->rw_pid != 0)
272  kill(rw->rw_pid, SIGTERM);
273  else
274  {
275  /* Report never-started, now-terminated worker as dead. */
277  }
278  }
279  continue;
280  }
281 
282  /*
283  * If the worker is marked for termination, we don't need to add it to
284  * the registered workers list; we can just free the slot. However, if
285  * bgw_notify_pid is set, the process that registered the worker may
286  * need to know that we've processed the terminate request, so be sure
287  * to signal it.
288  */
289  if (slot->terminate)
290  {
291  int notify_pid;
292 
293  /*
294  * We need a memory barrier here to make sure that the load of
295  * bgw_notify_pid and the update of parallel_terminate_count
296  * complete before the store to in_use.
297  */
298  notify_pid = slot->worker.bgw_notify_pid;
299  if ((slot->worker.bgw_flags & BGWORKER_CLASS_PARALLEL) != 0)
302  slot->pid = 0;
303  slot->in_use = false;
304  if (notify_pid != 0)
305  kill(notify_pid, SIGUSR1);
306 
307  continue;
308  }
309 
310  /*
311  * Copy the registration data into the registered workers list.
312  */
313  rw = malloc(sizeof(RegisteredBgWorker));
314  if (rw == NULL)
315  {
316  ereport(LOG,
317  (errcode(ERRCODE_OUT_OF_MEMORY),
318  errmsg("out of memory")));
319  return;
320  }
321 
322  /*
323  * Copy strings in a paranoid way. If shared memory is corrupted, the
324  * source data might not even be NUL-terminated.
325  */
327  slot->worker.bgw_name, BGW_MAXLEN);
332 
333  /*
334  * Copy various fixed-size fields.
335  *
336  * flags, start_time, and restart_time are examined by the postmaster,
337  * but nothing too bad will happen if they are corrupted. The
338  * remaining fields will only be examined by the child process. It
339  * might crash, but we won't.
340  */
341  rw->rw_worker.bgw_flags = slot->worker.bgw_flags;
344  rw->rw_worker.bgw_main = slot->worker.bgw_main;
346  memcpy(rw->rw_worker.bgw_extra, slot->worker.bgw_extra, BGW_EXTRALEN);
347 
348  /*
349  * Copy the PID to be notified about state changes, but only if the
350  * postmaster knows about a backend with that PID. It isn't an error
351  * if the postmaster doesn't know about the PID, because the backend
352  * that requested the worker could have died (or been killed) just
353  * after doing so. Nonetheless, at least until we get some experience
354  * with how this plays out in the wild, log a message at a relative
355  * high debug level.
356  */
359  {
360  elog(DEBUG1, "worker notification PID %lu is not valid",
361  (long) rw->rw_worker.bgw_notify_pid);
362  rw->rw_worker.bgw_notify_pid = 0;
363  }
364 
365  /* Initialize postmaster bookkeeping. */
366  rw->rw_backend = NULL;
367  rw->rw_pid = 0;
368  rw->rw_child_slot = 0;
369  rw->rw_crashed_at = 0;
370  rw->rw_shmem_slot = slotno;
371  rw->rw_terminate = false;
372 
373  /* Log it! */
374  ereport(DEBUG1,
375  (errmsg("registering background worker \"%s\"",
376  rw->rw_worker.bgw_name)));
377 
379  }
380 }
char bgw_extra[BGW_EXTRALEN]
Definition: bgworker.h:98
struct bkend * rw_backend
#define SIGUSR1
Definition: win32.h:211
#define DEBUG1
Definition: elog.h:25
static BackgroundWorkerArray * BackgroundWorkerData
Definition: bgworker.c:109
static void slist_push_head(slist_head *head, slist_node *node)
Definition: ilist.h:574
int bgw_restart_time
Definition: bgworker.h:93
int errcode(int sqlerrcode)
Definition: elog.c:575
#define BGWORKER_CLASS_PARALLEL
Definition: bgworker.h:67
void ascii_safe_strlcpy(char *dest, const char *src, size_t destsiz)
Definition: ascii.c:173
#define LOG
Definition: elog.h:26
char bgw_function_name[BGW_MAXLEN]
Definition: bgworker.h:96
#define malloc(a)
Definition: header.h:50
Datum bgw_main_arg
Definition: bgworker.h:97
void ReportBackgroundWorkerPID(RegisteredBgWorker *rw)
Definition: bgworker.c:420
bgworker_main_type bgw_main
Definition: bgworker.h:94
bool PostmasterMarkPIDForWorkerNotify(int pid)
Definition: postmaster.c:5788
slist_head BackgroundWorkerList
Definition: bgworker.c:41
#define ereport(elevel, rest)
Definition: elog.h:122
static RegisteredBgWorker * FindRegisteredWorkerBySlotNumber(int slotno)
Definition: bgworker.c:199
#define pg_memory_barrier()
Definition: atomics.h:147
#define NULL
Definition: c.h:229
char bgw_name[BGW_MAXLEN]
Definition: bgworker.h:90
BackgroundWorker worker
Definition: bgworker.c:81
#define pg_read_barrier()
Definition: atomics.h:160
#define BGW_MAXLEN
Definition: bgworker.h:85
BgWorkerStartTime bgw_start_time
Definition: bgworker.h:92
int errmsg(const char *fmt,...)
Definition: elog.c:797
uint32 parallel_terminate_count
Definition: bgworker.c:99
pid_t bgw_notify_pid
Definition: bgworker.h:99
int max_worker_processes
Definition: globals.c:124
#define elog
Definition: elog.h:219
BackgroundWorker rw_worker
BackgroundWorkerSlot slot[FLEXIBLE_ARRAY_MEMBER]
Definition: bgworker.c:100
char bgw_library_name[BGW_MAXLEN]
Definition: bgworker.h:95
#define BGW_EXTRALEN
Definition: bgworker.h:86
void BackgroundWorkerStopNotifications ( pid_t  pid)

Definition at line 473 of file bgworker.c.

References BackgroundWorker::bgw_notify_pid, slist_iter::cur, RegisteredBgWorker::rw_worker, slist_container, and slist_foreach.

Referenced by CleanupBackend(), and CleanupBackgroundWorker().

474 {
475  slist_iter siter;
476 
478  {
479  RegisteredBgWorker *rw;
480 
481  rw = slist_container(RegisteredBgWorker, rw_lnode, siter.cur);
482  if (rw->rw_worker.bgw_notify_pid == pid)
483  rw->rw_worker.bgw_notify_pid = 0;
484  }
485 }
slist_node * cur
Definition: ilist.h:226
slist_head BackgroundWorkerList
Definition: bgworker.c:41
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
#define slist_foreach(iter, lhead)
Definition: ilist.h:700
pid_t bgw_notify_pid
Definition: bgworker.h:99
BackgroundWorker rw_worker
static void bgworker_die ( SIGNAL_ARGS  )
static

Definition at line 613 of file bgworker.c.

References BackgroundWorker::bgw_name, BlockSig, ereport, errcode(), errmsg(), FATAL, MyBgworkerEntry, and PG_SETMASK.

Referenced by StartBackgroundWorker().

614 {
616 
617  ereport(FATAL,
618  (errcode(ERRCODE_ADMIN_SHUTDOWN),
619  errmsg("terminating background worker \"%s\" due to administrator command",
621 }
int errcode(int sqlerrcode)
Definition: elog.c:575
BackgroundWorker * MyBgworkerEntry
Definition: postmaster.c:189
#define PG_SETMASK(mask)
Definition: pqsignal.h:19
#define FATAL
Definition: elog.h:52
#define ereport(elevel, rest)
Definition: elog.h:122
sigset_t BlockSig
Definition: pqsignal.c:22
char bgw_name[BGW_MAXLEN]
Definition: bgworker.h:90
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void bgworker_quickdie ( SIGNAL_ARGS  )
static

Definition at line 583 of file bgworker.c.

References BlockSig, on_exit_reset(), PG_SETMASK, and SIGQUIT.

Referenced by StartBackgroundWorker().

584 {
585  sigaddset(&BlockSig, SIGQUIT); /* prevent nested calls */
587 
588  /*
589  * We DO NOT want to run proc_exit() callbacks -- we're here because
590  * shared memory may be corrupted, so we don't want to try to clean up our
591  * transaction. Just nail the windows shut and get out of town. Now that
592  * there's an atexit callback to prevent third-party code from breaking
593  * things by calling exit() directly, we have to reset the callbacks
594  * explicitly to make this work as intended.
595  */
596  on_exit_reset();
597 
598  /*
599  * Note we do exit(2) not exit(0). This is to force the postmaster into a
600  * system reset cycle if some idiot DBA sends a manual SIGQUIT to a random
601  * backend. This is necessary precisely because we don't clean up our
602  * shared memory state. (The "dead man switch" mechanism in pmsignal.c
603  * should ensure the postmaster sees this as a crash, too, but no harm in
604  * being doubly sure.)
605  */
606  exit(2);
607 }
#define SIGQUIT
Definition: win32.h:197
#define PG_SETMASK(mask)
Definition: pqsignal.h:19
void on_exit_reset(void)
Definition: ipc.c:396
sigset_t BlockSig
Definition: pqsignal.c:22
static void bgworker_sigusr1_handler ( SIGNAL_ARGS  )
static

Definition at line 630 of file bgworker.c.

References latch_sigusr1_handler().

Referenced by StartBackgroundWorker().

631 {
632  int save_errno = errno;
633 
635 
636  errno = save_errno;
637 }
void latch_sigusr1_handler(void)
Definition: latch.c:1572
static RegisteredBgWorker* FindRegisteredWorkerBySlotNumber ( int  slotno)
static

Definition at line 199 of file bgworker.c.

References slist_iter::cur, NULL, RegisteredBgWorker::rw_shmem_slot, slist_container, and slist_foreach.

Referenced by BackgroundWorkerStateChange().

200 {
201  slist_iter siter;
202 
204  {
205  RegisteredBgWorker *rw;
206 
207  rw = slist_container(RegisteredBgWorker, rw_lnode, siter.cur);
208  if (rw->rw_shmem_slot == slotno)
209  return rw;
210  }
211 
212  return NULL;
213 }
slist_node * cur
Definition: ilist.h:226
slist_head BackgroundWorkerList
Definition: bgworker.c:41
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
#define NULL
Definition: c.h:229
#define slist_foreach(iter, lhead)
Definition: ilist.h:700
void ForgetBackgroundWorker ( slist_mutable_iter cur)

Definition at line 392 of file bgworker.c.

References Assert, BackgroundWorker::bgw_flags, BackgroundWorker::bgw_name, BGWORKER_CLASS_PARALLEL, slist_mutable_iter::cur, DEBUG1, ereport, errmsg(), free, BackgroundWorkerSlot::in_use, max_worker_processes, BackgroundWorkerArray::parallel_terminate_count, RegisteredBgWorker::rw_shmem_slot, RegisteredBgWorker::rw_worker, slist_container, slist_delete_current(), and BackgroundWorkerArray::slot.

Referenced by DetermineSleepTime(), maybe_start_bgworker(), and ReportBackgroundWorkerExit().

393 {
394  RegisteredBgWorker *rw;
395  BackgroundWorkerSlot *slot;
396 
397  rw = slist_container(RegisteredBgWorker, rw_lnode, cur->cur);
398 
403 
404  slot->in_use = false;
405 
406  ereport(DEBUG1,
407  (errmsg("unregistering background worker \"%s\"",
408  rw->rw_worker.bgw_name)));
409 
411  free(rw);
412 }
#define DEBUG1
Definition: elog.h:25
static BackgroundWorkerArray * BackgroundWorkerData
Definition: bgworker.c:109
slist_node * cur
Definition: ilist.h:241
#define BGWORKER_CLASS_PARALLEL
Definition: bgworker.h:67
#define ereport(elevel, rest)
Definition: elog.h:122
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
#define free(a)
Definition: header.h:65
char bgw_name[BGW_MAXLEN]
Definition: bgworker.h:90
#define Assert(condition)
Definition: c.h:675
int errmsg(const char *fmt,...)
Definition: elog.c:797
uint32 parallel_terminate_count
Definition: bgworker.c:99
int max_worker_processes
Definition: globals.c:124
static void slist_delete_current(slist_mutable_iter *iter)
Definition: ilist.h:652
BackgroundWorker rw_worker
BackgroundWorkerSlot slot[FLEXIBLE_ARRAY_MEMBER]
Definition: bgworker.c:100
BgwHandleStatus GetBackgroundWorkerPid ( BackgroundWorkerHandle handle,
pid_t *  pidp 
)

Definition at line 1004 of file bgworker.c.

References Assert, BGWH_NOT_YET_STARTED, BGWH_STARTED, BGWH_STOPPED, BackgroundWorkerSlot::generation, BackgroundWorkerHandle::generation, InvalidPid, LW_SHARED, LWLockAcquire(), LWLockRelease(), max_worker_processes, BackgroundWorkerSlot::pid, BackgroundWorkerArray::slot, and BackgroundWorkerHandle::slot.

Referenced by check_worker_status(), shm_mq_counterparty_gone(), shm_mq_wait_internal(), WaitForBackgroundWorkerShutdown(), WaitForBackgroundWorkerStartup(), and WaitForReplicationWorkerAttach().

1005 {
1006  BackgroundWorkerSlot *slot;
1007  pid_t pid;
1008 
1009  Assert(handle->slot < max_worker_processes);
1010  slot = &BackgroundWorkerData->slot[handle->slot];
1011 
1012  /*
1013  * We could probably arrange to synchronize access to data using memory
1014  * barriers only, but for now, let's just keep it simple and grab the
1015  * lock. It seems unlikely that there will be enough traffic here to
1016  * result in meaningful contention.
1017  */
1018  LWLockAcquire(BackgroundWorkerLock, LW_SHARED);
1019 
1020  /*
1021  * The generation number can't be concurrently changed while we hold the
1022  * lock. The pid, which is updated by the postmaster, can change at any
1023  * time, but we assume such changes are atomic. So the value we read
1024  * won't be garbage, but it might be out of date by the time the caller
1025  * examines it (but that's unavoidable anyway).
1026  */
1027  if (handle->generation != slot->generation)
1028  pid = 0;
1029  else
1030  pid = slot->pid;
1031 
1032  /* All done. */
1033  LWLockRelease(BackgroundWorkerLock);
1034 
1035  if (pid == 0)
1036  return BGWH_STOPPED;
1037  else if (pid == InvalidPid)
1038  return BGWH_NOT_YET_STARTED;
1039  *pidp = pid;
1040  return BGWH_STARTED;
1041 }
static BackgroundWorkerArray * BackgroundWorkerData
Definition: bgworker.c:109
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define Assert(condition)
Definition: c.h:675
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
int max_worker_processes
Definition: globals.c:124
BackgroundWorkerSlot slot[FLEXIBLE_ARRAY_MEMBER]
Definition: bgworker.c:100
#define InvalidPid
Definition: miscadmin.h:31
void RegisterBackgroundWorker ( BackgroundWorker worker)

Definition at line 805 of file bgworker.c.

References BackgroundWorker::bgw_main, BackgroundWorker::bgw_name, BackgroundWorker::bgw_notify_pid, DEBUG1, ereport, errcode(), errdetail_plural(), errhint(), errmsg(), i, InternalBGWorkers, IsUnderPostmaster, LOG, malloc, max_worker_processes, NULL, process_shared_preload_libraries_in_progress, RegisteredBgWorker::rw_backend, RegisteredBgWorker::rw_child_slot, RegisteredBgWorker::rw_crashed_at, RegisteredBgWorker::rw_lnode, RegisteredBgWorker::rw_pid, RegisteredBgWorker::rw_terminate, RegisteredBgWorker::rw_worker, SanityCheckBackgroundWorker(), and slist_push_head().

Referenced by _PG_init(), and ApplyLauncherRegister().

806 {
807  RegisteredBgWorker *rw;
808  static int numworkers = 0;
809  bool internal = false;
810  int i;
811 
812  if (!IsUnderPostmaster)
813  ereport(DEBUG1,
814  (errmsg("registering background worker \"%s\"", worker->bgw_name)));
815 
816  for (i = 0; InternalBGWorkers[i]; i++)
817  {
818  if (worker->bgw_main == InternalBGWorkers[i])
819  {
820  internal = true;
821  break;
822  }
823  }
824 
826  {
827  if (!IsUnderPostmaster)
828  ereport(LOG,
829  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
830  errmsg("background worker \"%s\": must be registered in shared_preload_libraries",
831  worker->bgw_name)));
832  return;
833  }
834 
835  if (!SanityCheckBackgroundWorker(worker, LOG))
836  return;
837 
838  if (worker->bgw_notify_pid != 0)
839  {
840  ereport(LOG,
841  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
842  errmsg("background worker \"%s\": only dynamic background workers can request notification",
843  worker->bgw_name)));
844  return;
845  }
846 
847  /*
848  * Enforce maximum number of workers. Note this is overly restrictive: we
849  * could allow more non-shmem-connected workers, because these don't count
850  * towards the MAX_BACKENDS limit elsewhere. For now, it doesn't seem
851  * important to relax this restriction.
852  */
853  if (++numworkers > max_worker_processes)
854  {
855  ereport(LOG,
856  (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
857  errmsg("too many background workers"),
858  errdetail_plural("Up to %d background worker can be registered with the current settings.",
859  "Up to %d background workers can be registered with the current settings.",
862  errhint("Consider increasing the configuration parameter \"max_worker_processes\".")));
863  return;
864  }
865 
866  /*
867  * Copy the registration data into the registered workers list.
868  */
869  rw = malloc(sizeof(RegisteredBgWorker));
870  if (rw == NULL)
871  {
872  ereport(LOG,
873  (errcode(ERRCODE_OUT_OF_MEMORY),
874  errmsg("out of memory")));
875  return;
876  }
877 
878  rw->rw_worker = *worker;
879  rw->rw_backend = NULL;
880  rw->rw_pid = 0;
881  rw->rw_child_slot = 0;
882  rw->rw_crashed_at = 0;
883  rw->rw_terminate = false;
884 
886 }
struct bkend * rw_backend
#define DEBUG1
Definition: elog.h:25
int errhint(const char *fmt,...)
Definition: elog.c:987
bool process_shared_preload_libraries_in_progress
Definition: miscinit.c:1417
static void slist_push_head(slist_head *head, slist_node *node)
Definition: ilist.h:574
int errcode(int sqlerrcode)
Definition: elog.c:575
#define LOG
Definition: elog.h:26
static const bgworker_main_type InternalBGWorkers[]
Definition: bgworker.c:115
#define malloc(a)
Definition: header.h:50
bgworker_main_type bgw_main
Definition: bgworker.h:94
slist_head BackgroundWorkerList
Definition: bgworker.c:41
bool IsUnderPostmaster
Definition: globals.c:100
#define ereport(elevel, rest)
Definition: elog.h:122
static bool SanityCheckBackgroundWorker(BackgroundWorker *worker, int elevel)
Definition: bgworker.c:542
#define NULL
Definition: c.h:229
char bgw_name[BGW_MAXLEN]
Definition: bgworker.h:90
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:965
int errmsg(const char *fmt,...)
Definition: elog.c:797
pid_t bgw_notify_pid
Definition: bgworker.h:99
int i
int max_worker_processes
Definition: globals.c:124
BackgroundWorker rw_worker
bool RegisterDynamicBackgroundWorker ( BackgroundWorker worker,
BackgroundWorkerHandle **  handle 
)

Definition at line 899 of file bgworker.c.

References BackgroundWorker::bgw_flags, BGWORKER_CLASS_PARALLEL, ERROR, BackgroundWorkerSlot::generation, BackgroundWorkerSlot::in_use, InvalidPid, IsUnderPostmaster, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), max_parallel_workers, palloc(), BackgroundWorkerArray::parallel_register_count, BackgroundWorkerArray::parallel_terminate_count, pg_write_barrier, BackgroundWorkerSlot::pid, PMSIGNAL_BACKGROUND_WORKER_CHANGE, SanityCheckBackgroundWorker(), SendPostmasterSignal(), BackgroundWorkerArray::slot, success, BackgroundWorkerSlot::terminate, BackgroundWorkerArray::total_slots, and BackgroundWorkerSlot::worker.

Referenced by LaunchParallelWorkers(), logicalrep_worker_launch(), setup_background_workers(), and worker_spi_launch().

901 {
902  int slotno;
903  bool success = false;
904  bool parallel;
905  uint64 generation = 0;
906 
907  /*
908  * We can't register dynamic background workers from the postmaster. If
909  * this is a standalone backend, we're the only process and can't start
910  * any more. In a multi-process environment, it might be theoretically
911  * possible, but we don't currently support it due to locking
912  * considerations; see comments on the BackgroundWorkerSlot data
913  * structure.
914  */
915  if (!IsUnderPostmaster)
916  return false;
917 
918  if (!SanityCheckBackgroundWorker(worker, ERROR))
919  return false;
920 
921  parallel = (worker->bgw_flags & BGWORKER_CLASS_PARALLEL) != 0;
922 
923  LWLockAcquire(BackgroundWorkerLock, LW_EXCLUSIVE);
924 
925  /*
926  * If this is a parallel worker, check whether there are already too many
927  * parallel workers; if so, don't register another one. Our view of
928  * parallel_terminate_count may be slightly stale, but that doesn't really
929  * matter: we would have gotten the same result if we'd arrived here
930  * slightly earlier anyway. There's no help for it, either, since the
931  * postmaster must not take locks; a memory barrier wouldn't guarantee
932  * anything useful.
933  */
937  {
938  LWLockRelease(BackgroundWorkerLock);
939  return false;
940  }
941 
942  /*
943  * Look for an unused slot. If we find one, grab it.
944  */
945  for (slotno = 0; slotno < BackgroundWorkerData->total_slots; ++slotno)
946  {
948 
949  if (!slot->in_use)
950  {
951  memcpy(&slot->worker, worker, sizeof(BackgroundWorker));
952  slot->pid = InvalidPid; /* indicates not started yet */
953  slot->generation++;
954  slot->terminate = false;
955  generation = slot->generation;
956  if (parallel)
958 
959  /*
960  * Make sure postmaster doesn't see the slot as in use before it
961  * sees the new contents.
962  */
964 
965  slot->in_use = true;
966  success = true;
967  break;
968  }
969  }
970 
971  LWLockRelease(BackgroundWorkerLock);
972 
973  /* If we found a slot, tell the postmaster to notice the change. */
974  if (success)
976 
977  /*
978  * If we found a slot and the user has provided a handle, initialize it.
979  */
980  if (success && handle)
981  {
982  *handle = palloc(sizeof(BackgroundWorkerHandle));
983  (*handle)->slot = slotno;
984  (*handle)->generation = generation;
985  }
986 
987  return success;
988 }
int max_parallel_workers
Definition: globals.c:125
static BackgroundWorkerArray * BackgroundWorkerData
Definition: bgworker.c:109
#define BGWORKER_CLASS_PARALLEL
Definition: bgworker.h:67
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define ERROR
Definition: elog.h:43
static bool success
Definition: pg_basebackup.c:96
uint32 parallel_register_count
Definition: bgworker.c:98
bool IsUnderPostmaster
Definition: globals.c:100
static bool SanityCheckBackgroundWorker(BackgroundWorker *worker, int elevel)
Definition: bgworker.c:542
BackgroundWorker worker
Definition: bgworker.c:81
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
void * palloc(Size size)
Definition: mcxt.c:849
uint32 parallel_terminate_count
Definition: bgworker.c:99
#define pg_write_barrier()
Definition: atomics.h:161
void SendPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:113
BackgroundWorkerSlot slot[FLEXIBLE_ARRAY_MEMBER]
Definition: bgworker.c:100
#define InvalidPid
Definition: miscadmin.h:31
void ReportBackgroundWorkerExit ( slist_mutable_iter cur)

Definition at line 439 of file bgworker.c.

References Assert, BGW_NEVER_RESTART, BackgroundWorker::bgw_notify_pid, BackgroundWorker::bgw_restart_time, slist_mutable_iter::cur, ForgetBackgroundWorker(), max_worker_processes, BackgroundWorkerSlot::pid, RegisteredBgWorker::rw_pid, RegisteredBgWorker::rw_shmem_slot, RegisteredBgWorker::rw_terminate, RegisteredBgWorker::rw_worker, SIGUSR1, slist_container, and BackgroundWorkerArray::slot.

Referenced by CleanupBackgroundWorker().

440 {
441  RegisteredBgWorker *rw;
442  BackgroundWorkerSlot *slot;
443  int notify_pid;
444 
445  rw = slist_container(RegisteredBgWorker, rw_lnode, cur->cur);
446 
449  slot->pid = rw->rw_pid;
450  notify_pid = rw->rw_worker.bgw_notify_pid;
451 
452  /*
453  * If this worker is slated for deregistration, do that before notifying
454  * the process which started it. Otherwise, if that process tries to
455  * reuse the slot immediately, it might not be available yet. In theory
456  * that could happen anyway if the process checks slot->pid at just the
457  * wrong moment, but this makes the window narrower.
458  */
459  if (rw->rw_terminate ||
462 
463  if (notify_pid != 0)
464  kill(notify_pid, SIGUSR1);
465 }
#define SIGUSR1
Definition: win32.h:211
static BackgroundWorkerArray * BackgroundWorkerData
Definition: bgworker.c:109
slist_node * cur
Definition: ilist.h:241
int bgw_restart_time
Definition: bgworker.h:93
void ForgetBackgroundWorker(slist_mutable_iter *cur)
Definition: bgworker.c:392
#define BGW_NEVER_RESTART
Definition: bgworker.h:84
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
#define Assert(condition)
Definition: c.h:675
pid_t bgw_notify_pid
Definition: bgworker.h:99
int max_worker_processes
Definition: globals.c:124
BackgroundWorker rw_worker
BackgroundWorkerSlot slot[FLEXIBLE_ARRAY_MEMBER]
Definition: bgworker.c:100
void ReportBackgroundWorkerPID ( RegisteredBgWorker rw)

Definition at line 420 of file bgworker.c.

References Assert, BackgroundWorker::bgw_notify_pid, max_worker_processes, BackgroundWorkerSlot::pid, RegisteredBgWorker::rw_pid, RegisteredBgWorker::rw_shmem_slot, RegisteredBgWorker::rw_worker, SIGUSR1, and BackgroundWorkerArray::slot.

Referenced by BackgroundWorkerStateChange(), and do_start_bgworker().

421 {
422  BackgroundWorkerSlot *slot;
423 
426  slot->pid = rw->rw_pid;
427 
428  if (rw->rw_worker.bgw_notify_pid != 0)
429  kill(rw->rw_worker.bgw_notify_pid, SIGUSR1);
430 }
#define SIGUSR1
Definition: win32.h:211
static BackgroundWorkerArray * BackgroundWorkerData
Definition: bgworker.c:109
#define Assert(condition)
Definition: c.h:675
pid_t bgw_notify_pid
Definition: bgworker.h:99
int max_worker_processes
Definition: globals.c:124
BackgroundWorker rw_worker
BackgroundWorkerSlot slot[FLEXIBLE_ARRAY_MEMBER]
Definition: bgworker.c:100
void ResetBackgroundWorkerCrashTimes ( void  )

Definition at line 495 of file bgworker.c.

References BGW_NEVER_RESTART, BackgroundWorker::bgw_restart_time, slist_mutable_iter::cur, RegisteredBgWorker::rw_crashed_at, RegisteredBgWorker::rw_worker, slist_container, and slist_foreach_modify.

Referenced by PostmasterStateMachine().

496 {
497  slist_mutable_iter iter;
498 
500  {
501  RegisteredBgWorker *rw;
502 
503  rw = slist_container(RegisteredBgWorker, rw_lnode, iter.cur);
504 
505  /*
506  * For workers that should not be restarted, we don't want to lose the
507  * information that they have crashed; otherwise, they would be
508  * restarted, which is wrong.
509  */
511  rw->rw_crashed_at = 0;
512  }
513 }
slist_node * cur
Definition: ilist.h:241
int bgw_restart_time
Definition: bgworker.h:93
#define slist_foreach_modify(iter, lhead)
Definition: ilist.h:716
slist_head BackgroundWorkerList
Definition: bgworker.c:41
#define BGW_NEVER_RESTART
Definition: bgworker.h:84
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
BackgroundWorker rw_worker
static bool SanityCheckBackgroundWorker ( BackgroundWorker worker,
int  elevel 
)
static

Definition at line 542 of file bgworker.c.

References BackgroundWorker::bgw_flags, BackgroundWorker::bgw_name, BGW_NEVER_RESTART, BackgroundWorker::bgw_restart_time, BackgroundWorker::bgw_start_time, BGWORKER_BACKEND_DATABASE_CONNECTION, BGWORKER_SHMEM_ACCESS, BgWorkerStart_PostmasterStart, ereport, errcode(), errmsg(), and USECS_PER_DAY.

Referenced by RegisterBackgroundWorker(), and RegisterDynamicBackgroundWorker().

543 {
544  /* sanity check for flags */
546  {
547  if (!(worker->bgw_flags & BGWORKER_SHMEM_ACCESS))
548  {
549  ereport(elevel,
550  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
551  errmsg("background worker \"%s\": must attach to shared memory in order to request a database connection",
552  worker->bgw_name)));
553  return false;
554  }
555 
557  {
558  ereport(elevel,
559  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
560  errmsg("background worker \"%s\": cannot request database access if starting at postmaster start",
561  worker->bgw_name)));
562  return false;
563  }
564 
565  /* XXX other checks? */
566  }
567 
568  if ((worker->bgw_restart_time < 0 &&
569  worker->bgw_restart_time != BGW_NEVER_RESTART) ||
570  (worker->bgw_restart_time > USECS_PER_DAY / 1000))
571  {
572  ereport(elevel,
573  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
574  errmsg("background worker \"%s\": invalid restart interval",
575  worker->bgw_name)));
576  return false;
577  }
578 
579  return true;
580 }
int bgw_restart_time
Definition: bgworker.h:93
int errcode(int sqlerrcode)
Definition: elog.c:575
#define BGWORKER_SHMEM_ACCESS
Definition: bgworker.h:52
#define BGW_NEVER_RESTART
Definition: bgworker.h:84
#define USECS_PER_DAY
Definition: timestamp.h:91
#define ereport(elevel, rest)
Definition: elog.h:122
static int elevel
Definition: vacuumlazy.c:137
char bgw_name[BGW_MAXLEN]
Definition: bgworker.h:90
#define BGWORKER_BACKEND_DATABASE_CONNECTION
Definition: bgworker.h:59
BgWorkerStartTime bgw_start_time
Definition: bgworker.h:92
int errmsg(const char *fmt,...)
Definition: elog.c:797
void StartBackgroundWorker ( void  )

Definition at line 646 of file bgworker.c.

References BaseInit(), BackgroundWorker::bgw_flags, BackgroundWorker::bgw_function_name, BackgroundWorker::bgw_library_name, BackgroundWorker::bgw_main, BackgroundWorker::bgw_main_arg, BackgroundWorker::bgw_name, BGWORKER_BACKEND_DATABASE_CONNECTION, bgworker_die(), bgworker_quickdie(), BGWORKER_SHMEM_ACCESS, bgworker_sigusr1_handler(), buf, dsm_detach_all(), elog, EmitErrorReport(), error_context_stack, FATAL, FloatExceptionHandler(), HOLD_INTERRUPTS, init_ps_display(), InitializeTimeouts(), InitProcess(), InitProcessing, IsBackgroundWorker, load_external_function(), MAXPGPATH, MyBgworkerEntry, NULL, PG_exception_stack, pg_usleep(), PGSharedMemoryDetach(), PostAuthDelay, pqsignal(), proc_exit(), procsignal_sigusr1_handler(), SetProcessingMode, SIG_DFL, SIG_IGN, SIGCHLD, SIGHUP, SIGPIPE, SIGQUIT, SIGUSR1, SIGUSR2, snprintf(), and StatementCancelHandler().

Referenced by do_start_bgworker().

647 {
648  sigjmp_buf local_sigjmp_buf;
649  char buf[MAXPGPATH];
651  bgworker_main_type entrypt;
652 
653  if (worker == NULL)
654  elog(FATAL, "unable to find bgworker entry");
655 
656  IsBackgroundWorker = true;
657 
658  /* Identify myself via ps */
659  snprintf(buf, MAXPGPATH, "bgworker: %s", worker->bgw_name);
660  init_ps_display(buf, "", "", "");
661 
662  /*
663  * If we're not supposed to have shared memory access, then detach from
664  * shared memory. If we didn't request shared memory access, the
665  * postmaster won't force a cluster-wide restart if we exit unexpectedly,
666  * so we'd better make sure that we don't mess anything up that would
667  * require that sort of cleanup.
668  */
669  if ((worker->bgw_flags & BGWORKER_SHMEM_ACCESS) == 0)
670  {
671  dsm_detach_all();
673  }
674 
676 
677  /* Apply PostAuthDelay */
678  if (PostAuthDelay > 0)
679  pg_usleep(PostAuthDelay * 1000000L);
680 
681  /*
682  * Set up signal handlers.
683  */
685  {
686  /*
687  * SIGINT is used to signal canceling the current action
688  */
692 
693  /* XXX Any other handlers needed here? */
694  }
695  else
696  {
697  pqsignal(SIGINT, SIG_IGN);
699  pqsignal(SIGFPE, SIG_IGN);
700  }
701  pqsignal(SIGTERM, bgworker_die);
703 
705  InitializeTimeouts(); /* establishes SIGALRM handler */
706 
710 
711  /*
712  * If an exception is encountered, processing resumes here.
713  *
714  * See notes in postgres.c about the design of this coding.
715  */
716  if (sigsetjmp(local_sigjmp_buf, 1) != 0)
717  {
718  /* Since not using PG_TRY, must reset error stack by hand */
720 
721  /* Prevent interrupts while cleaning up */
722  HOLD_INTERRUPTS();
723 
724  /* Report the error to the server log */
725  EmitErrorReport();
726 
727  /*
728  * Do we need more cleanup here? For shmem-connected bgworkers, we
729  * will call InitProcess below, which will install ProcKill as exit
730  * callback. That will take care of releasing locks, etc.
731  */
732 
733  /* and go away */
734  proc_exit(1);
735  }
736 
737  /* We can now handle ereport(ERROR) */
738  PG_exception_stack = &local_sigjmp_buf;
739 
740  /*
741  * If the background worker request shared memory access, set that up now;
742  * else, detach all shared memory segments.
743  */
744  if (worker->bgw_flags & BGWORKER_SHMEM_ACCESS)
745  {
746  /*
747  * Early initialization. Some of this could be useful even for
748  * background workers that aren't using shared memory, but they can
749  * call the individual startup routines for those subsystems if
750  * needed.
751  */
752  BaseInit();
753 
754  /*
755  * Create a per-backend PGPROC struct in shared memory, except in the
756  * EXEC_BACKEND case where this was done in SubPostmasterMain. We must
757  * do this before we can use LWLocks (and in the EXEC_BACKEND case we
758  * already had to do some stuff with LWLocks).
759  */
760 #ifndef EXEC_BACKEND
761  InitProcess();
762 #endif
763  }
764 
765  /*
766  * If bgw_main is set, we use that value as the initial entrypoint.
767  * However, if the library containing the entrypoint wasn't loaded at
768  * postmaster startup time, passing it as a direct function pointer is not
769  * possible. To work around that, we allow callers for whom a function
770  * pointer is not available to pass a library name (which will be loaded,
771  * if necessary) and a function name (which will be looked up in the named
772  * library).
773  */
774  if (worker->bgw_main != NULL)
775  entrypt = worker->bgw_main;
776  else
777  entrypt = (bgworker_main_type)
779  worker->bgw_function_name,
780  true, NULL);
781 
782  /*
783  * Note that in normal processes, we would call InitPostgres here. For a
784  * worker, however, we don't know what database to connect to, yet; so we
785  * need to wait until the user code does it via
786  * BackgroundWorkerInitializeConnection().
787  */
788 
789  /*
790  * Now invoke the user-defined worker code
791  */
792  entrypt(worker->bgw_main_arg);
793 
794  /* ... and if it returns, we're done */
795  proc_exit(0);
796 }
void InitializeTimeouts(void)
Definition: timeout.c:340
static void bgworker_sigusr1_handler(SIGNAL_ARGS)
Definition: bgworker.c:630
#define SIGUSR1
Definition: win32.h:211
void proc_exit(int code)
Definition: ipc.c:99
#define SetProcessingMode(mode)
Definition: miscadmin.h:371
BackgroundWorker * MyBgworkerEntry
Definition: postmaster.c:189
void BaseInit(void)
Definition: postinit.c:517
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define BGWORKER_SHMEM_ACCESS
Definition: bgworker.h:52
char bgw_function_name[BGW_MAXLEN]
Definition: bgworker.h:96
#define SIGQUIT
Definition: win32.h:197
void PGSharedMemoryDetach(void)
Definition: sysv_shmem.c:768
void StatementCancelHandler(SIGNAL_ARGS)
Definition: postgres.c:2650
bool IsBackgroundWorker
Definition: globals.c:102
ErrorContextCallback * error_context_stack
Definition: elog.c:88
void pg_usleep(long microsec)
Definition: signal.c:53
Datum bgw_main_arg
Definition: bgworker.h:97
#define SIG_IGN
Definition: win32.h:193
#define FATAL
Definition: elog.h:52
void(* bgworker_main_type)(Datum main_arg)
Definition: bgworker.h:71
bgworker_main_type bgw_main
Definition: bgworker.h:94
#define MAXPGPATH
void InitProcess(void)
Definition: proc.c:287
static char * buf
Definition: pg_test_fsync.c:65
PGFunction load_external_function(char *filename, char *funcname, bool signalNotFound, void **filehandle)
Definition: dfmgr.c:94
int PostAuthDelay
Definition: postgres.c:97
void EmitErrorReport(void)
Definition: elog.c:1446
#define SIGPIPE
Definition: win32.h:201
#define SIGHUP
Definition: win32.h:196
#define SIG_DFL
Definition: win32.h:191
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:168
#define NULL
Definition: c.h:229
char bgw_name[BGW_MAXLEN]
Definition: bgworker.h:90
#define BGWORKER_BACKEND_DATABASE_CONNECTION
Definition: bgworker.h:59
void dsm_detach_all(void)
Definition: dsm.c:654
sigjmp_buf * PG_exception_stack
Definition: elog.c:90
#define HOLD_INTERRUPTS()
Definition: miscadmin.h:114
void FloatExceptionHandler(SIGNAL_ARGS)
Definition: postgres.c:2671
static void bgworker_die(SIGNAL_ARGS)
Definition: bgworker.c:613
#define elog
Definition: elog.h:219
static void bgworker_quickdie(SIGNAL_ARGS)
Definition: bgworker.c:583
void procsignal_sigusr1_handler(SIGNAL_ARGS)
Definition: procsignal.c:260
#define SIGCHLD
Definition: win32.h:206
char bgw_library_name[BGW_MAXLEN]
Definition: bgworker.h:95
#define SIGUSR2
Definition: win32.h:212
void init_ps_display(const char *username, const char *dbname, const char *host_info, const char *initial_str)
Definition: ps_status.c:244
void TerminateBackgroundWorker ( BackgroundWorkerHandle handle)

Definition at line 1134 of file bgworker.c.

References Assert, BackgroundWorkerSlot::generation, BackgroundWorkerHandle::generation, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), max_worker_processes, PMSIGNAL_BACKGROUND_WORKER_CHANGE, SendPostmasterSignal(), BackgroundWorkerArray::slot, BackgroundWorkerHandle::slot, and BackgroundWorkerSlot::terminate.

Referenced by cleanup_background_workers(), and DestroyParallelContext().

1135 {
1136  BackgroundWorkerSlot *slot;
1137  bool signal_postmaster = false;
1138 
1139  Assert(handle->slot < max_worker_processes);
1140  slot = &BackgroundWorkerData->slot[handle->slot];
1141 
1142  /* Set terminate flag in shared memory, unless slot has been reused. */
1143  LWLockAcquire(BackgroundWorkerLock, LW_EXCLUSIVE);
1144  if (handle->generation == slot->generation)
1145  {
1146  slot->terminate = true;
1147  signal_postmaster = true;
1148  }
1149  LWLockRelease(BackgroundWorkerLock);
1150 
1151  /* Make sure the postmaster notices the change to shared memory. */
1152  if (signal_postmaster)
1154 }
static BackgroundWorkerArray * BackgroundWorkerData
Definition: bgworker.c:109
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define Assert(condition)
Definition: c.h:675
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
int max_worker_processes
Definition: globals.c:124
void SendPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:113
BackgroundWorkerSlot slot[FLEXIBLE_ARRAY_MEMBER]
Definition: bgworker.c:100
BgwHandleStatus WaitForBackgroundWorkerShutdown ( BackgroundWorkerHandle handle)

Definition at line 1095 of file bgworker.c.

References BGWH_POSTMASTER_DIED, BGWH_STOPPED, CHECK_FOR_INTERRUPTS, GetBackgroundWorkerPid(), MyProc, PGPROC::procLatch, ResetLatch(), status(), WAIT_EVENT_BGWORKER_SHUTDOWN, WaitLatch(), WL_LATCH_SET, and WL_POSTMASTER_DEATH.

Referenced by WaitForParallelWorkersToExit().

1096 {
1098  int rc;
1099 
1100  for (;;)
1101  {
1102  pid_t pid;
1103 
1105 
1106  status = GetBackgroundWorkerPid(handle, &pid);
1107  if (status == BGWH_STOPPED)
1108  break;
1109 
1110  rc = WaitLatch(&MyProc->procLatch,
1113 
1114  if (rc & WL_POSTMASTER_DEATH)
1115  {
1116  status = BGWH_POSTMASTER_DIED;
1117  break;
1118  }
1119 
1121  }
1122 
1123  return status;
1124 }
PGPROC * MyProc
Definition: proc.c:67
void ResetLatch(volatile Latch *latch)
Definition: latch.c:461
Latch procLatch
Definition: proc.h:98
int WaitLatch(volatile Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:300
BgwHandleStatus
Definition: bgworker.h:102
#define WL_POSTMASTER_DEATH
Definition: latch.h:128
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224
#define WL_LATCH_SET
Definition: latch.h:124
BgwHandleStatus GetBackgroundWorkerPid(BackgroundWorkerHandle *handle, pid_t *pidp)
Definition: bgworker.c:1004
BgwHandleStatus WaitForBackgroundWorkerStartup ( BackgroundWorkerHandle handle,
pid_t *  pidp 
)

Definition at line 1053 of file bgworker.c.

References BGWH_NOT_YET_STARTED, BGWH_POSTMASTER_DIED, BGWH_STARTED, CHECK_FOR_INTERRUPTS, GetBackgroundWorkerPid(), MyLatch, ResetLatch(), status(), WAIT_EVENT_BGWORKER_STARTUP, WaitLatch(), WL_LATCH_SET, and WL_POSTMASTER_DEATH.

Referenced by worker_spi_launch().

1054 {
1056  int rc;
1057 
1058  for (;;)
1059  {
1060  pid_t pid;
1061 
1063 
1064  status = GetBackgroundWorkerPid(handle, &pid);
1065  if (status == BGWH_STARTED)
1066  *pidp = pid;
1067  if (status != BGWH_NOT_YET_STARTED)
1068  break;
1069 
1070  rc = WaitLatch(MyLatch,
1073 
1074  if (rc & WL_POSTMASTER_DEATH)
1075  {
1076  status = BGWH_POSTMASTER_DIED;
1077  break;
1078  }
1079 
1081  }
1082 
1083  return status;
1084 }
void ResetLatch(volatile Latch *latch)
Definition: latch.c:461
int WaitLatch(volatile Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:300
BgwHandleStatus
Definition: bgworker.h:102
#define WL_POSTMASTER_DEATH
Definition: latch.h:128
struct Latch * MyLatch
Definition: globals.c:51
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224
#define WL_LATCH_SET
Definition: latch.h:124
BgwHandleStatus GetBackgroundWorkerPid(BackgroundWorkerHandle *handle, pid_t *pidp)
Definition: bgworker.c:1004

Variable Documentation

BackgroundWorkerArray* BackgroundWorkerData
static

Definition at line 109 of file bgworker.c.

slist_head BackgroundWorkerList = SLIST_STATIC_INIT(BackgroundWorkerList)
const bgworker_main_type InternalBGWorkers[]
static
Initial value:
= {
}
void ApplyLauncherMain(Datum main_arg)
Definition: launcher.c:632
#define NULL
Definition: c.h:229

Definition at line 115 of file bgworker.c.

Referenced by RegisterBackgroundWorker().