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 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:671
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:353
int max_worker_processes
Definition: globals.c:124
#define offsetof(type, field)
Definition: c.h:551
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:45
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:5781
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:226
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 438 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().

439 {
440  slist_iter siter;
441 
443  {
444  RegisteredBgWorker *rw;
445 
446  rw = slist_container(RegisteredBgWorker, rw_lnode, siter.cur);
447  if (rw->rw_worker.bgw_notify_pid == pid)
448  rw->rw_worker.bgw_notify_pid = 0;
449  }
450 }
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 578 of file bgworker.c.

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

Referenced by StartBackgroundWorker().

579 {
581 
582  ereport(FATAL,
583  (errcode(ERRCODE_ADMIN_SHUTDOWN),
584  errmsg("terminating background worker \"%s\" due to administrator command",
586 }
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 548 of file bgworker.c.

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

Referenced by StartBackgroundWorker().

549 {
550  sigaddset(&BlockSig, SIGQUIT); /* prevent nested calls */
552 
553  /*
554  * We DO NOT want to run proc_exit() callbacks -- we're here because
555  * shared memory may be corrupted, so we don't want to try to clean up our
556  * transaction. Just nail the windows shut and get out of town. Now that
557  * there's an atexit callback to prevent third-party code from breaking
558  * things by calling exit() directly, we have to reset the callbacks
559  * explicitly to make this work as intended.
560  */
561  on_exit_reset();
562 
563  /*
564  * Note we do exit(2) not exit(0). This is to force the postmaster into a
565  * system reset cycle if some idiot DBA sends a manual SIGQUIT to a random
566  * backend. This is necessary precisely because we don't clean up our
567  * shared memory state. (The "dead man switch" mechanism in pmsignal.c
568  * should ensure the postmaster sees this as a crash, too, but no harm in
569  * being doubly sure.)
570  */
571  exit(2);
572 }
#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 595 of file bgworker.c.

References latch_sigusr1_handler().

Referenced by StartBackgroundWorker().

596 {
597  int save_errno = errno;
598 
600 
601  errno = save_errno;
602 }
void latch_sigusr1_handler(void)
Definition: latch.c:1541
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:226
#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(), and maybe_start_bgworker().

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:60
char bgw_name[BGW_MAXLEN]
Definition: bgworker.h:90
#define Assert(condition)
Definition: c.h:671
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 969 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().

970 {
971  BackgroundWorkerSlot *slot;
972  pid_t pid;
973 
974  Assert(handle->slot < max_worker_processes);
975  slot = &BackgroundWorkerData->slot[handle->slot];
976 
977  /*
978  * We could probably arrange to synchronize access to data using memory
979  * barriers only, but for now, let's just keep it simple and grab the
980  * lock. It seems unlikely that there will be enough traffic here to
981  * result in meaningful contention.
982  */
983  LWLockAcquire(BackgroundWorkerLock, LW_SHARED);
984 
985  /*
986  * The generation number can't be concurrently changed while we hold the
987  * lock. The pid, which is updated by the postmaster, can change at any
988  * time, but we assume such changes are atomic. So the value we read
989  * won't be garbage, but it might be out of date by the time the caller
990  * examines it (but that's unavoidable anyway).
991  */
992  if (handle->generation != slot->generation)
993  pid = 0;
994  else
995  pid = slot->pid;
996 
997  /* All done. */
998  LWLockRelease(BackgroundWorkerLock);
999 
1000  if (pid == 0)
1001  return BGWH_STOPPED;
1002  else if (pid == InvalidPid)
1003  return BGWH_NOT_YET_STARTED;
1004  *pidp = pid;
1005  return BGWH_STARTED;
1006 }
static BackgroundWorkerArray * BackgroundWorkerData
Definition: bgworker.c:109
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
#define Assert(condition)
Definition: c.h:671
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
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 770 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().

771 {
772  RegisteredBgWorker *rw;
773  static int numworkers = 0;
774  bool internal = false;
775  int i;
776 
777  if (!IsUnderPostmaster)
778  ereport(DEBUG1,
779  (errmsg("registering background worker \"%s\"", worker->bgw_name)));
780 
781  for (i = 0; InternalBGWorkers[i]; i++)
782  {
783  if (worker->bgw_main == InternalBGWorkers[i])
784  {
785  internal = true;
786  break;
787  }
788  }
789 
791  {
792  if (!IsUnderPostmaster)
793  ereport(LOG,
794  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
795  errmsg("background worker \"%s\": must be registered in shared_preload_libraries",
796  worker->bgw_name)));
797  return;
798  }
799 
800  if (!SanityCheckBackgroundWorker(worker, LOG))
801  return;
802 
803  if (worker->bgw_notify_pid != 0)
804  {
805  ereport(LOG,
806  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
807  errmsg("background worker \"%s\": only dynamic background workers can request notification",
808  worker->bgw_name)));
809  return;
810  }
811 
812  /*
813  * Enforce maximum number of workers. Note this is overly restrictive: we
814  * could allow more non-shmem-connected workers, because these don't count
815  * towards the MAX_BACKENDS limit elsewhere. For now, it doesn't seem
816  * important to relax this restriction.
817  */
818  if (++numworkers > max_worker_processes)
819  {
820  ereport(LOG,
821  (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
822  errmsg("too many background workers"),
823  errdetail_plural("Up to %d background worker can be registered with the current settings.",
824  "Up to %d background workers can be registered with the current settings.",
827  errhint("Consider increasing the configuration parameter \"max_worker_processes\".")));
828  return;
829  }
830 
831  /*
832  * Copy the registration data into the registered workers list.
833  */
834  rw = malloc(sizeof(RegisteredBgWorker));
835  if (rw == NULL)
836  {
837  ereport(LOG,
838  (errcode(ERRCODE_OUT_OF_MEMORY),
839  errmsg("out of memory")));
840  return;
841  }
842 
843  rw->rw_worker = *worker;
844  rw->rw_backend = NULL;
845  rw->rw_pid = 0;
846  rw->rw_child_slot = 0;
847  rw->rw_crashed_at = 0;
848  rw->rw_terminate = false;
849 
851 }
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:1401
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:45
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:507
#define NULL
Definition: c.h:226
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 864 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().

866 {
867  int slotno;
868  bool success = false;
869  bool parallel;
870  uint64 generation = 0;
871 
872  /*
873  * We can't register dynamic background workers from the postmaster. If
874  * this is a standalone backend, we're the only process and can't start
875  * any more. In a multi-process environment, it might be theoretically
876  * possible, but we don't currently support it due to locking
877  * considerations; see comments on the BackgroundWorkerSlot data
878  * structure.
879  */
880  if (!IsUnderPostmaster)
881  return false;
882 
883  if (!SanityCheckBackgroundWorker(worker, ERROR))
884  return false;
885 
886  parallel = (worker->bgw_flags & BGWORKER_CLASS_PARALLEL) != 0;
887 
888  LWLockAcquire(BackgroundWorkerLock, LW_EXCLUSIVE);
889 
890  /*
891  * If this is a parallel worker, check whether there are already too many
892  * parallel workers; if so, don't register another one. Our view of
893  * parallel_terminate_count may be slightly stale, but that doesn't really
894  * matter: we would have gotten the same result if we'd arrived here
895  * slightly earlier anyway. There's no help for it, either, since the
896  * postmaster must not take locks; a memory barrier wouldn't guarantee
897  * anything useful.
898  */
902  {
903  LWLockRelease(BackgroundWorkerLock);
904  return false;
905  }
906 
907  /*
908  * Look for an unused slot. If we find one, grab it.
909  */
910  for (slotno = 0; slotno < BackgroundWorkerData->total_slots; ++slotno)
911  {
913 
914  if (!slot->in_use)
915  {
916  memcpy(&slot->worker, worker, sizeof(BackgroundWorker));
917  slot->pid = InvalidPid; /* indicates not started yet */
918  slot->generation++;
919  slot->terminate = false;
920  generation = slot->generation;
921  if (parallel)
923 
924  /*
925  * Make sure postmaster doesn't see the slot as in use before it
926  * sees the new contents.
927  */
929 
930  slot->in_use = true;
931  success = true;
932  break;
933  }
934  }
935 
936  LWLockRelease(BackgroundWorkerLock);
937 
938  /* If we found a slot, tell the postmaster to notice the change. */
939  if (success)
941 
942  /*
943  * If we found a slot and the user has provided a handle, initialize it.
944  */
945  if (success && handle)
946  {
947  *handle = palloc(sizeof(BackgroundWorkerHandle));
948  (*handle)->slot = slotno;
949  (*handle)->generation = generation;
950  }
951 
952  return success;
953 }
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:1714
#define ERROR
Definition: elog.h:43
static bool success
Definition: pg_basebackup.c:99
uint32 parallel_register_count
Definition: bgworker.c:98
bool IsUnderPostmaster
Definition: globals.c:100
static bool SanityCheckBackgroundWorker(BackgroundWorker *worker, int elevel)
Definition: bgworker.c:507
BackgroundWorker worker
Definition: bgworker.c:81
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
void * palloc(Size size)
Definition: mcxt.c:891
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 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(), CleanupBackgroundWorker(), 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:671
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 460 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().

461 {
462  slist_mutable_iter iter;
463 
465  {
466  RegisteredBgWorker *rw;
467 
468  rw = slist_container(RegisteredBgWorker, rw_lnode, iter.cur);
469 
470  /*
471  * For workers that should not be restarted, we don't want to lose the
472  * information that they have crashed; otherwise, they would be
473  * restarted, which is wrong.
474  */
476  rw->rw_crashed_at = 0;
477  }
478 }
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 507 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().

508 {
509  /* sanity check for flags */
511  {
512  if (!(worker->bgw_flags & BGWORKER_SHMEM_ACCESS))
513  {
514  ereport(elevel,
515  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
516  errmsg("background worker \"%s\": must attach to shared memory in order to request a database connection",
517  worker->bgw_name)));
518  return false;
519  }
520 
522  {
523  ereport(elevel,
524  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
525  errmsg("background worker \"%s\": cannot request database access if starting at postmaster start",
526  worker->bgw_name)));
527  return false;
528  }
529 
530  /* XXX other checks? */
531  }
532 
533  if ((worker->bgw_restart_time < 0 &&
534  worker->bgw_restart_time != BGW_NEVER_RESTART) ||
535  (worker->bgw_restart_time > USECS_PER_DAY / 1000))
536  {
537  ereport(elevel,
538  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
539  errmsg("background worker \"%s\": invalid restart interval",
540  worker->bgw_name)));
541  return false;
542  }
543 
544  return true;
545 }
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:103
#define ereport(elevel, rest)
Definition: elog.h:122
static int elevel
Definition: vacuumlazy.c:136
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 611 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().

612 {
613  sigjmp_buf local_sigjmp_buf;
614  char buf[MAXPGPATH];
616  bgworker_main_type entrypt;
617 
618  if (worker == NULL)
619  elog(FATAL, "unable to find bgworker entry");
620 
621  IsBackgroundWorker = true;
622 
623  /* Identify myself via ps */
624  snprintf(buf, MAXPGPATH, "bgworker: %s", worker->bgw_name);
625  init_ps_display(buf, "", "", "");
626 
627  /*
628  * If we're not supposed to have shared memory access, then detach from
629  * shared memory. If we didn't request shared memory access, the
630  * postmaster won't force a cluster-wide restart if we exit unexpectedly,
631  * so we'd better make sure that we don't mess anything up that would
632  * require that sort of cleanup.
633  */
634  if ((worker->bgw_flags & BGWORKER_SHMEM_ACCESS) == 0)
635  {
636  dsm_detach_all();
638  }
639 
641 
642  /* Apply PostAuthDelay */
643  if (PostAuthDelay > 0)
644  pg_usleep(PostAuthDelay * 1000000L);
645 
646  /*
647  * Set up signal handlers.
648  */
650  {
651  /*
652  * SIGINT is used to signal canceling the current action
653  */
657 
658  /* XXX Any other handlers needed here? */
659  }
660  else
661  {
662  pqsignal(SIGINT, SIG_IGN);
664  pqsignal(SIGFPE, SIG_IGN);
665  }
666  pqsignal(SIGTERM, bgworker_die);
668 
670  InitializeTimeouts(); /* establishes SIGALRM handler */
671 
675 
676  /*
677  * If an exception is encountered, processing resumes here.
678  *
679  * See notes in postgres.c about the design of this coding.
680  */
681  if (sigsetjmp(local_sigjmp_buf, 1) != 0)
682  {
683  /* Since not using PG_TRY, must reset error stack by hand */
685 
686  /* Prevent interrupts while cleaning up */
687  HOLD_INTERRUPTS();
688 
689  /* Report the error to the server log */
690  EmitErrorReport();
691 
692  /*
693  * Do we need more cleanup here? For shmem-connected bgworkers, we
694  * will call InitProcess below, which will install ProcKill as exit
695  * callback. That will take care of releasing locks, etc.
696  */
697 
698  /* and go away */
699  proc_exit(1);
700  }
701 
702  /* We can now handle ereport(ERROR) */
703  PG_exception_stack = &local_sigjmp_buf;
704 
705  /*
706  * If the background worker request shared memory access, set that up now;
707  * else, detach all shared memory segments.
708  */
709  if (worker->bgw_flags & BGWORKER_SHMEM_ACCESS)
710  {
711  /*
712  * Early initialization. Some of this could be useful even for
713  * background workers that aren't using shared memory, but they can
714  * call the individual startup routines for those subsystems if
715  * needed.
716  */
717  BaseInit();
718 
719  /*
720  * Create a per-backend PGPROC struct in shared memory, except in the
721  * EXEC_BACKEND case where this was done in SubPostmasterMain. We must
722  * do this before we can use LWLocks (and in the EXEC_BACKEND case we
723  * already had to do some stuff with LWLocks).
724  */
725 #ifndef EXEC_BACKEND
726  InitProcess();
727 #endif
728  }
729 
730  /*
731  * If bgw_main is set, we use that value as the initial entrypoint.
732  * However, if the library containing the entrypoint wasn't loaded at
733  * postmaster startup time, passing it as a direct function pointer is not
734  * possible. To work around that, we allow callers for whom a function
735  * pointer is not available to pass a library name (which will be loaded,
736  * if necessary) and a function name (which will be looked up in the named
737  * library).
738  */
739  if (worker->bgw_main != NULL)
740  entrypt = worker->bgw_main;
741  else
742  entrypt = (bgworker_main_type)
744  worker->bgw_function_name,
745  true, NULL);
746 
747  /*
748  * Note that in normal processes, we would call InitPostgres here. For a
749  * worker, however, we don't know what database to connect to, yet; so we
750  * need to wait until the user code does it via
751  * BackgroundWorkerInitializeConnection().
752  */
753 
754  /*
755  * Now invoke the user-defined worker code
756  */
757  entrypt(worker->bgw_main_arg);
758 
759  /* ... and if it returns, we're done */
760  proc_exit(0);
761 }
void InitializeTimeouts(void)
Definition: timeout.c:340
static void bgworker_sigusr1_handler(SIGNAL_ARGS)
Definition: bgworker.c:595
#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:2648
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:226
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:655
sigjmp_buf * PG_exception_stack
Definition: elog.c:90
#define HOLD_INTERRUPTS()
Definition: miscadmin.h:114
void FloatExceptionHandler(SIGNAL_ARGS)
Definition: postgres.c:2669
static void bgworker_die(SIGNAL_ARGS)
Definition: bgworker.c:578
#define elog
Definition: elog.h:219
static void bgworker_quickdie(SIGNAL_ARGS)
Definition: bgworker.c:548
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 1099 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().

1100 {
1101  BackgroundWorkerSlot *slot;
1102  bool signal_postmaster = false;
1103 
1104  Assert(handle->slot < max_worker_processes);
1105  slot = &BackgroundWorkerData->slot[handle->slot];
1106 
1107  /* Set terminate flag in shared memory, unless slot has been reused. */
1108  LWLockAcquire(BackgroundWorkerLock, LW_EXCLUSIVE);
1109  if (handle->generation == slot->generation)
1110  {
1111  slot->terminate = true;
1112  signal_postmaster = true;
1113  }
1114  LWLockRelease(BackgroundWorkerLock);
1115 
1116  /* Make sure the postmaster notices the change to shared memory. */
1117  if (signal_postmaster)
1119 }
static BackgroundWorkerArray * BackgroundWorkerData
Definition: bgworker.c:109
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
#define Assert(condition)
Definition: c.h:671
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
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 1060 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().

1061 {
1063  int rc;
1064 
1065  for (;;)
1066  {
1067  pid_t pid;
1068 
1070 
1071  status = GetBackgroundWorkerPid(handle, &pid);
1072  if (status == BGWH_STOPPED)
1073  break;
1074 
1075  rc = WaitLatch(&MyProc->procLatch,
1078 
1079  if (rc & WL_POSTMASTER_DEATH)
1080  {
1081  status = BGWH_POSTMASTER_DIED;
1082  break;
1083  }
1084 
1086  }
1087 
1088  return status;
1089 }
PGPROC * MyProc
Definition: proc.c:67
void ResetLatch(volatile Latch *latch)
Definition: latch.c:462
Latch procLatch
Definition: proc.h:93
int WaitLatch(volatile Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:301
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:222
#define WL_LATCH_SET
Definition: latch.h:124
BgwHandleStatus GetBackgroundWorkerPid(BackgroundWorkerHandle *handle, pid_t *pidp)
Definition: bgworker.c:969
BgwHandleStatus WaitForBackgroundWorkerStartup ( BackgroundWorkerHandle handle,
pid_t *  pidp 
)

Definition at line 1018 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().

1019 {
1021  int rc;
1022 
1023  for (;;)
1024  {
1025  pid_t pid;
1026 
1028 
1029  status = GetBackgroundWorkerPid(handle, &pid);
1030  if (status == BGWH_STARTED)
1031  *pidp = pid;
1032  if (status != BGWH_NOT_YET_STARTED)
1033  break;
1034 
1035  rc = WaitLatch(MyLatch,
1038 
1039  if (rc & WL_POSTMASTER_DEATH)
1040  {
1041  status = BGWH_POSTMASTER_DIED;
1042  break;
1043  }
1044 
1046  }
1047 
1048  return status;
1049 }
void ResetLatch(volatile Latch *latch)
Definition: latch.c:462
int WaitLatch(volatile Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:301
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:222
#define WL_LATCH_SET
Definition: latch.h:124
BgwHandleStatus GetBackgroundWorkerPid(BackgroundWorkerHandle *handle, pid_t *pidp)
Definition: bgworker.c:969

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:558
#define NULL
Definition: c.h:226

Definition at line 115 of file bgworker.c.

Referenced by RegisterBackgroundWorker().