LCOV - code coverage report
Current view: top level - src/backend/postmaster - bgworker.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 281 337 83.4 %
Date: 2023-12-01 19:11:07 Functions: 20 21 95.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*--------------------------------------------------------------------
       2             :  * bgworker.c
       3             :  *      POSTGRES pluggable background workers implementation
       4             :  *
       5             :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       6             :  *
       7             :  * IDENTIFICATION
       8             :  *    src/backend/postmaster/bgworker.c
       9             :  *
      10             :  *-------------------------------------------------------------------------
      11             :  */
      12             : 
      13             : #include "postgres.h"
      14             : 
      15             : #include "access/parallel.h"
      16             : #include "libpq/pqsignal.h"
      17             : #include "miscadmin.h"
      18             : #include "pgstat.h"
      19             : #include "port/atomics.h"
      20             : #include "postmaster/bgworker_internals.h"
      21             : #include "postmaster/interrupt.h"
      22             : #include "postmaster/postmaster.h"
      23             : #include "replication/logicallauncher.h"
      24             : #include "replication/logicalworker.h"
      25             : #include "storage/dsm.h"
      26             : #include "storage/ipc.h"
      27             : #include "storage/latch.h"
      28             : #include "storage/lwlock.h"
      29             : #include "storage/pg_shmem.h"
      30             : #include "storage/pmsignal.h"
      31             : #include "storage/proc.h"
      32             : #include "storage/procsignal.h"
      33             : #include "storage/shmem.h"
      34             : #include "tcop/tcopprot.h"
      35             : #include "utils/ascii.h"
      36             : #include "utils/memutils.h"
      37             : #include "utils/ps_status.h"
      38             : #include "utils/timeout.h"
      39             : 
      40             : /*
      41             :  * The postmaster's list of registered background workers, in private memory.
      42             :  */
      43             : slist_head  BackgroundWorkerList = SLIST_STATIC_INIT(BackgroundWorkerList);
      44             : 
      45             : /*
      46             :  * BackgroundWorkerSlots exist in shared memory and can be accessed (via
      47             :  * the BackgroundWorkerArray) by both the postmaster and by regular backends.
      48             :  * However, the postmaster cannot take locks, even spinlocks, because this
      49             :  * might allow it to crash or become wedged if shared memory gets corrupted.
      50             :  * Such an outcome is intolerable.  Therefore, we need a lockless protocol
      51             :  * for coordinating access to this data.
      52             :  *
      53             :  * The 'in_use' flag is used to hand off responsibility for the slot between
      54             :  * the postmaster and the rest of the system.  When 'in_use' is false,
      55             :  * the postmaster will ignore the slot entirely, except for the 'in_use' flag
      56             :  * itself, which it may read.  In this state, regular backends may modify the
      57             :  * slot.  Once a backend sets 'in_use' to true, the slot becomes the
      58             :  * responsibility of the postmaster.  Regular backends may no longer modify it,
      59             :  * but the postmaster may examine it.  Thus, a backend initializing a slot
      60             :  * must fully initialize the slot - and insert a write memory barrier - before
      61             :  * marking it as in use.
      62             :  *
      63             :  * As an exception, however, even when the slot is in use, regular backends
      64             :  * may set the 'terminate' flag for a slot, telling the postmaster not
      65             :  * to restart it.  Once the background worker is no longer running, the slot
      66             :  * will be released for reuse.
      67             :  *
      68             :  * In addition to coordinating with the postmaster, backends modifying this
      69             :  * data structure must coordinate with each other.  Since they can take locks,
      70             :  * this is straightforward: any backend wishing to manipulate a slot must
      71             :  * take BackgroundWorkerLock in exclusive mode.  Backends wishing to read
      72             :  * data that might get concurrently modified by other backends should take
      73             :  * this lock in shared mode.  No matter what, backends reading this data
      74             :  * structure must be able to tolerate concurrent modifications by the
      75             :  * postmaster.
      76             :  */
      77             : typedef struct BackgroundWorkerSlot
      78             : {
      79             :     bool        in_use;
      80             :     bool        terminate;
      81             :     pid_t       pid;            /* InvalidPid = not started yet; 0 = dead */
      82             :     uint64      generation;     /* incremented when slot is recycled */
      83             :     BackgroundWorker worker;
      84             : } BackgroundWorkerSlot;
      85             : 
      86             : /*
      87             :  * In order to limit the total number of parallel workers (according to
      88             :  * max_parallel_workers GUC), we maintain the number of active parallel
      89             :  * workers.  Since the postmaster cannot take locks, two variables are used for
      90             :  * this purpose: the number of registered parallel workers (modified by the
      91             :  * backends, protected by BackgroundWorkerLock) and the number of terminated
      92             :  * parallel workers (modified only by the postmaster, lockless).  The active
      93             :  * number of parallel workers is the number of registered workers minus the
      94             :  * terminated ones.  These counters can of course overflow, but it's not
      95             :  * important here since the subtraction will still give the right number.
      96             :  */
      97             : typedef struct BackgroundWorkerArray
      98             : {
      99             :     int         total_slots;
     100             :     uint32      parallel_register_count;
     101             :     uint32      parallel_terminate_count;
     102             :     BackgroundWorkerSlot slot[FLEXIBLE_ARRAY_MEMBER];
     103             : } BackgroundWorkerArray;
     104             : 
     105             : struct BackgroundWorkerHandle
     106             : {
     107             :     int         slot;
     108             :     uint64      generation;
     109             : };
     110             : 
     111             : static BackgroundWorkerArray *BackgroundWorkerData;
     112             : 
     113             : /*
     114             :  * List of internal background worker entry points.  We need this for
     115             :  * reasons explained in LookupBackgroundWorkerFunction(), below.
     116             :  */
     117             : static const struct
     118             : {
     119             :     const char *fn_name;
     120             :     bgworker_main_type fn_addr;
     121             : }           InternalBGWorkers[] =
     122             : 
     123             : {
     124             :     {
     125             :         "ParallelWorkerMain", ParallelWorkerMain
     126             :     },
     127             :     {
     128             :         "ApplyLauncherMain", ApplyLauncherMain
     129             :     },
     130             :     {
     131             :         "ApplyWorkerMain", ApplyWorkerMain
     132             :     },
     133             :     {
     134             :         "ParallelApplyWorkerMain", ParallelApplyWorkerMain
     135             :     },
     136             :     {
     137             :         "TablesyncWorkerMain", TablesyncWorkerMain
     138             :     }
     139             : };
     140             : 
     141             : /* Private functions. */
     142             : static bgworker_main_type LookupBackgroundWorkerFunction(const char *libraryname, const char *funcname);
     143             : 
     144             : 
     145             : /*
     146             :  * Calculate shared memory needed.
     147             :  */
     148             : Size
     149        4496 : BackgroundWorkerShmemSize(void)
     150             : {
     151             :     Size        size;
     152             : 
     153             :     /* Array of workers is variably sized. */
     154        4496 :     size = offsetof(BackgroundWorkerArray, slot);
     155        4496 :     size = add_size(size, mul_size(max_worker_processes,
     156             :                                    sizeof(BackgroundWorkerSlot)));
     157             : 
     158        4496 :     return size;
     159             : }
     160             : 
     161             : /*
     162             :  * Initialize shared memory.
     163             :  */
     164             : void
     165        1562 : BackgroundWorkerShmemInit(void)
     166             : {
     167             :     bool        found;
     168             : 
     169        1562 :     BackgroundWorkerData = ShmemInitStruct("Background Worker Data",
     170             :                                            BackgroundWorkerShmemSize(),
     171             :                                            &found);
     172        1562 :     if (!IsUnderPostmaster)
     173             :     {
     174             :         slist_iter  siter;
     175        1562 :         int         slotno = 0;
     176             : 
     177        1562 :         BackgroundWorkerData->total_slots = max_worker_processes;
     178        1562 :         BackgroundWorkerData->parallel_register_count = 0;
     179        1562 :         BackgroundWorkerData->parallel_terminate_count = 0;
     180             : 
     181             :         /*
     182             :          * Copy contents of worker list into shared memory.  Record the shared
     183             :          * memory slot assigned to each worker.  This ensures a 1-to-1
     184             :          * correspondence between the postmaster's private list and the array
     185             :          * in shared memory.
     186             :          */
     187        2830 :         slist_foreach(siter, &BackgroundWorkerList)
     188             :         {
     189        1268 :             BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
     190             :             RegisteredBgWorker *rw;
     191             : 
     192        1268 :             rw = slist_container(RegisteredBgWorker, rw_lnode, siter.cur);
     193             :             Assert(slotno < max_worker_processes);
     194        1268 :             slot->in_use = true;
     195        1268 :             slot->terminate = false;
     196        1268 :             slot->pid = InvalidPid;
     197        1268 :             slot->generation = 0;
     198        1268 :             rw->rw_shmem_slot = slotno;
     199        1268 :             rw->rw_worker.bgw_notify_pid = 0;    /* might be reinit after crash */
     200        1268 :             memcpy(&slot->worker, &rw->rw_worker, sizeof(BackgroundWorker));
     201        1268 :             ++slotno;
     202             :         }
     203             : 
     204             :         /*
     205             :          * Mark any remaining slots as not in use.
     206             :          */
     207       12838 :         while (slotno < max_worker_processes)
     208             :         {
     209       11276 :             BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
     210             : 
     211       11276 :             slot->in_use = false;
     212       11276 :             ++slotno;
     213             :         }
     214             :     }
     215             :     else
     216             :         Assert(found);
     217        1562 : }
     218             : 
     219             : /*
     220             :  * Search the postmaster's backend-private list of RegisteredBgWorker objects
     221             :  * for the one that maps to the given slot number.
     222             :  */
     223             : static RegisteredBgWorker *
     224        6372 : FindRegisteredWorkerBySlotNumber(int slotno)
     225             : {
     226             :     slist_iter  siter;
     227             : 
     228       15426 :     slist_foreach(siter, &BackgroundWorkerList)
     229             :     {
     230             :         RegisteredBgWorker *rw;
     231             : 
     232       12106 :         rw = slist_container(RegisteredBgWorker, rw_lnode, siter.cur);
     233       12106 :         if (rw->rw_shmem_slot == slotno)
     234        3052 :             return rw;
     235             :     }
     236             : 
     237        3320 :     return NULL;
     238             : }
     239             : 
     240             : /*
     241             :  * Notice changes to shared memory made by other backends.
     242             :  * Accept new worker requests only if allow_new_workers is true.
     243             :  *
     244             :  * This code runs in the postmaster, so we must be very careful not to assume
     245             :  * that shared memory contents are sane.  Otherwise, a rogue backend could
     246             :  * take out the postmaster.
     247             :  */
     248             : void
     249        1906 : BackgroundWorkerStateChange(bool allow_new_workers)
     250             : {
     251             :     int         slotno;
     252             : 
     253             :     /*
     254             :      * The total number of slots stored in shared memory should match our
     255             :      * notion of max_worker_processes.  If it does not, something is very
     256             :      * wrong.  Further down, we always refer to this value as
     257             :      * max_worker_processes, in case shared memory gets corrupted while we're
     258             :      * looping.
     259             :      */
     260        1906 :     if (max_worker_processes != BackgroundWorkerData->total_slots)
     261             :     {
     262           0 :         ereport(LOG,
     263             :                 (errmsg("inconsistent background worker state (max_worker_processes=%d, total_slots=%d)",
     264             :                         max_worker_processes,
     265             :                         BackgroundWorkerData->total_slots)));
     266           0 :         return;
     267             :     }
     268             : 
     269             :     /*
     270             :      * Iterate through slots, looking for newly-registered workers or workers
     271             :      * who must die.
     272             :      */
     273       17442 :     for (slotno = 0; slotno < max_worker_processes; ++slotno)
     274             :     {
     275       15536 :         BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
     276             :         RegisteredBgWorker *rw;
     277             : 
     278       15536 :         if (!slot->in_use)
     279        9164 :             continue;
     280             : 
     281             :         /*
     282             :          * Make sure we don't see the in_use flag before the updated slot
     283             :          * contents.
     284             :          */
     285        6372 :         pg_read_barrier();
     286             : 
     287             :         /* See whether we already know about this worker. */
     288        6372 :         rw = FindRegisteredWorkerBySlotNumber(slotno);
     289        6372 :         if (rw != NULL)
     290             :         {
     291             :             /*
     292             :              * In general, the worker data can't change after it's initially
     293             :              * registered.  However, someone can set the terminate flag.
     294             :              */
     295        3052 :             if (slot->terminate && !rw->rw_terminate)
     296             :             {
     297           6 :                 rw->rw_terminate = true;
     298           6 :                 if (rw->rw_pid != 0)
     299           6 :                     kill(rw->rw_pid, SIGTERM);
     300             :                 else
     301             :                 {
     302             :                     /* Report never-started, now-terminated worker as dead. */
     303           0 :                     ReportBackgroundWorkerPID(rw);
     304             :                 }
     305             :             }
     306        3052 :             continue;
     307             :         }
     308             : 
     309             :         /*
     310             :          * If we aren't allowing new workers, then immediately mark it for
     311             :          * termination; the next stanza will take care of cleaning it up.
     312             :          * Doing this ensures that any process waiting for the worker will get
     313             :          * awoken, even though the worker will never be allowed to run.
     314             :          */
     315        3320 :         if (!allow_new_workers)
     316           0 :             slot->terminate = true;
     317             : 
     318             :         /*
     319             :          * If the worker is marked for termination, we don't need to add it to
     320             :          * the registered workers list; we can just free the slot. However, if
     321             :          * bgw_notify_pid is set, the process that registered the worker may
     322             :          * need to know that we've processed the terminate request, so be sure
     323             :          * to signal it.
     324             :          */
     325        3320 :         if (slot->terminate)
     326             :         {
     327             :             int         notify_pid;
     328             : 
     329             :             /*
     330             :              * We need a memory barrier here to make sure that the load of
     331             :              * bgw_notify_pid and the update of parallel_terminate_count
     332             :              * complete before the store to in_use.
     333             :              */
     334           0 :             notify_pid = slot->worker.bgw_notify_pid;
     335           0 :             if ((slot->worker.bgw_flags & BGWORKER_CLASS_PARALLEL) != 0)
     336           0 :                 BackgroundWorkerData->parallel_terminate_count++;
     337           0 :             slot->pid = 0;
     338             : 
     339           0 :             pg_memory_barrier();
     340           0 :             slot->in_use = false;
     341             : 
     342           0 :             if (notify_pid != 0)
     343           0 :                 kill(notify_pid, SIGUSR1);
     344             : 
     345           0 :             continue;
     346             :         }
     347             : 
     348             :         /*
     349             :          * Copy the registration data into the registered workers list.
     350             :          */
     351        3320 :         rw = MemoryContextAllocExtended(PostmasterContext,
     352             :                                         sizeof(RegisteredBgWorker),
     353             :                                         MCXT_ALLOC_NO_OOM);
     354        3320 :         if (rw == NULL)
     355             :         {
     356           0 :             ereport(LOG,
     357             :                     (errcode(ERRCODE_OUT_OF_MEMORY),
     358             :                      errmsg("out of memory")));
     359           0 :             return;
     360             :         }
     361             : 
     362             :         /*
     363             :          * Copy strings in a paranoid way.  If shared memory is corrupted, the
     364             :          * source data might not even be NUL-terminated.
     365             :          */
     366        3320 :         ascii_safe_strlcpy(rw->rw_worker.bgw_name,
     367        3320 :                            slot->worker.bgw_name, BGW_MAXLEN);
     368        3320 :         ascii_safe_strlcpy(rw->rw_worker.bgw_type,
     369        3320 :                            slot->worker.bgw_type, BGW_MAXLEN);
     370        3320 :         ascii_safe_strlcpy(rw->rw_worker.bgw_library_name,
     371        3320 :                            slot->worker.bgw_library_name, MAXPGPATH);
     372        3320 :         ascii_safe_strlcpy(rw->rw_worker.bgw_function_name,
     373        3320 :                            slot->worker.bgw_function_name, BGW_MAXLEN);
     374             : 
     375             :         /*
     376             :          * Copy various fixed-size fields.
     377             :          *
     378             :          * flags, start_time, and restart_time are examined by the postmaster,
     379             :          * but nothing too bad will happen if they are corrupted.  The
     380             :          * remaining fields will only be examined by the child process.  It
     381             :          * might crash, but we won't.
     382             :          */
     383        3320 :         rw->rw_worker.bgw_flags = slot->worker.bgw_flags;
     384        3320 :         rw->rw_worker.bgw_start_time = slot->worker.bgw_start_time;
     385        3320 :         rw->rw_worker.bgw_restart_time = slot->worker.bgw_restart_time;
     386        3320 :         rw->rw_worker.bgw_main_arg = slot->worker.bgw_main_arg;
     387        3320 :         memcpy(rw->rw_worker.bgw_extra, slot->worker.bgw_extra, BGW_EXTRALEN);
     388             : 
     389             :         /*
     390             :          * Copy the PID to be notified about state changes, but only if the
     391             :          * postmaster knows about a backend with that PID.  It isn't an error
     392             :          * if the postmaster doesn't know about the PID, because the backend
     393             :          * that requested the worker could have died (or been killed) just
     394             :          * after doing so.  Nonetheless, at least until we get some experience
     395             :          * with how this plays out in the wild, log a message at a relative
     396             :          * high debug level.
     397             :          */
     398        3320 :         rw->rw_worker.bgw_notify_pid = slot->worker.bgw_notify_pid;
     399        3320 :         if (!PostmasterMarkPIDForWorkerNotify(rw->rw_worker.bgw_notify_pid))
     400             :         {
     401           0 :             elog(DEBUG1, "worker notification PID %d is not valid",
     402             :                  (int) rw->rw_worker.bgw_notify_pid);
     403           0 :             rw->rw_worker.bgw_notify_pid = 0;
     404             :         }
     405             : 
     406             :         /* Initialize postmaster bookkeeping. */
     407        3320 :         rw->rw_backend = NULL;
     408        3320 :         rw->rw_pid = 0;
     409        3320 :         rw->rw_child_slot = 0;
     410        3320 :         rw->rw_crashed_at = 0;
     411        3320 :         rw->rw_shmem_slot = slotno;
     412        3320 :         rw->rw_terminate = false;
     413             : 
     414             :         /* Log it! */
     415        3320 :         ereport(DEBUG1,
     416             :                 (errmsg_internal("registering background worker \"%s\"",
     417             :                                  rw->rw_worker.bgw_name)));
     418             : 
     419        3320 :         slist_push_head(&BackgroundWorkerList, &rw->rw_lnode);
     420             :     }
     421             : }
     422             : 
     423             : /*
     424             :  * Forget about a background worker that's no longer needed.
     425             :  *
     426             :  * The worker must be identified by passing an slist_mutable_iter that
     427             :  * points to it.  This convention allows deletion of workers during
     428             :  * searches of the worker list, and saves having to search the list again.
     429             :  *
     430             :  * Caller is responsible for notifying bgw_notify_pid, if appropriate.
     431             :  *
     432             :  * This function must be invoked only in the postmaster.
     433             :  */
     434             : void
     435        3320 : ForgetBackgroundWorker(slist_mutable_iter *cur)
     436             : {
     437             :     RegisteredBgWorker *rw;
     438             :     BackgroundWorkerSlot *slot;
     439             : 
     440        3320 :     rw = slist_container(RegisteredBgWorker, rw_lnode, cur->cur);
     441             : 
     442             :     Assert(rw->rw_shmem_slot < max_worker_processes);
     443        3320 :     slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
     444             :     Assert(slot->in_use);
     445             : 
     446             :     /*
     447             :      * We need a memory barrier here to make sure that the update of
     448             :      * parallel_terminate_count completes before the store to in_use.
     449             :      */
     450        3320 :     if ((rw->rw_worker.bgw_flags & BGWORKER_CLASS_PARALLEL) != 0)
     451        2594 :         BackgroundWorkerData->parallel_terminate_count++;
     452             : 
     453        3320 :     pg_memory_barrier();
     454        3320 :     slot->in_use = false;
     455             : 
     456        3320 :     ereport(DEBUG1,
     457             :             (errmsg_internal("unregistering background worker \"%s\"",
     458             :                              rw->rw_worker.bgw_name)));
     459             : 
     460        3320 :     slist_delete_current(cur);
     461        3320 :     pfree(rw);
     462        3320 : }
     463             : 
     464             : /*
     465             :  * Report the PID of a newly-launched background worker in shared memory.
     466             :  *
     467             :  * This function should only be called from the postmaster.
     468             :  */
     469             : void
     470        4430 : ReportBackgroundWorkerPID(RegisteredBgWorker *rw)
     471             : {
     472             :     BackgroundWorkerSlot *slot;
     473             : 
     474             :     Assert(rw->rw_shmem_slot < max_worker_processes);
     475        4430 :     slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
     476        4430 :     slot->pid = rw->rw_pid;
     477             : 
     478        4430 :     if (rw->rw_worker.bgw_notify_pid != 0)
     479        3320 :         kill(rw->rw_worker.bgw_notify_pid, SIGUSR1);
     480        4430 : }
     481             : 
     482             : /*
     483             :  * Report that the PID of a background worker is now zero because a
     484             :  * previously-running background worker has exited.
     485             :  *
     486             :  * This function should only be called from the postmaster.
     487             :  */
     488             : void
     489        3940 : ReportBackgroundWorkerExit(slist_mutable_iter *cur)
     490             : {
     491             :     RegisteredBgWorker *rw;
     492             :     BackgroundWorkerSlot *slot;
     493             :     int         notify_pid;
     494             : 
     495        3940 :     rw = slist_container(RegisteredBgWorker, rw_lnode, cur->cur);
     496             : 
     497             :     Assert(rw->rw_shmem_slot < max_worker_processes);
     498        3940 :     slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
     499        3940 :     slot->pid = rw->rw_pid;
     500        3940 :     notify_pid = rw->rw_worker.bgw_notify_pid;
     501             : 
     502             :     /*
     503             :      * If this worker is slated for deregistration, do that before notifying
     504             :      * the process which started it.  Otherwise, if that process tries to
     505             :      * reuse the slot immediately, it might not be available yet.  In theory
     506             :      * that could happen anyway if the process checks slot->pid at just the
     507             :      * wrong moment, but this makes the window narrower.
     508             :      */
     509        3940 :     if (rw->rw_terminate ||
     510         924 :         rw->rw_worker.bgw_restart_time == BGW_NEVER_RESTART)
     511        3298 :         ForgetBackgroundWorker(cur);
     512             : 
     513        3940 :     if (notify_pid != 0)
     514        3252 :         kill(notify_pid, SIGUSR1);
     515        3940 : }
     516             : 
     517             : /*
     518             :  * Cancel SIGUSR1 notifications for a PID belonging to an exiting backend.
     519             :  *
     520             :  * This function should only be called from the postmaster.
     521             :  */
     522             : void
     523         396 : BackgroundWorkerStopNotifications(pid_t pid)
     524             : {
     525             :     slist_iter  siter;
     526             : 
     527        1238 :     slist_foreach(siter, &BackgroundWorkerList)
     528             :     {
     529             :         RegisteredBgWorker *rw;
     530             : 
     531         842 :         rw = slist_container(RegisteredBgWorker, rw_lnode, siter.cur);
     532         842 :         if (rw->rw_worker.bgw_notify_pid == pid)
     533          50 :             rw->rw_worker.bgw_notify_pid = 0;
     534             :     }
     535         396 : }
     536             : 
     537             : /*
     538             :  * Cancel any not-yet-started worker requests that have waiting processes.
     539             :  *
     540             :  * This is called during a normal ("smart" or "fast") database shutdown.
     541             :  * After this point, no new background workers will be started, so anything
     542             :  * that might be waiting for them needs to be kicked off its wait.  We do
     543             :  * that by canceling the bgworker registration entirely, which is perhaps
     544             :  * overkill, but since we're shutting down it does not matter whether the
     545             :  * registration record sticks around.
     546             :  *
     547             :  * This function should only be called from the postmaster.
     548             :  */
     549             : void
     550         734 : ForgetUnstartedBackgroundWorkers(void)
     551             : {
     552             :     slist_mutable_iter iter;
     553             : 
     554        1496 :     slist_foreach_modify(iter, &BackgroundWorkerList)
     555             :     {
     556             :         RegisteredBgWorker *rw;
     557             :         BackgroundWorkerSlot *slot;
     558             : 
     559         762 :         rw = slist_container(RegisteredBgWorker, rw_lnode, iter.cur);
     560             :         Assert(rw->rw_shmem_slot < max_worker_processes);
     561         762 :         slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
     562             : 
     563             :         /* If it's not yet started, and there's someone waiting ... */
     564         762 :         if (slot->pid == InvalidPid &&
     565          62 :             rw->rw_worker.bgw_notify_pid != 0)
     566             :         {
     567             :             /* ... then zap it, and notify the waiter */
     568           0 :             int         notify_pid = rw->rw_worker.bgw_notify_pid;
     569             : 
     570           0 :             ForgetBackgroundWorker(&iter);
     571           0 :             if (notify_pid != 0)
     572           0 :                 kill(notify_pid, SIGUSR1);
     573             :         }
     574             :     }
     575         734 : }
     576             : 
     577             : /*
     578             :  * Reset background worker crash state.
     579             :  *
     580             :  * We assume that, after a crash-and-restart cycle, background workers without
     581             :  * the never-restart flag should be restarted immediately, instead of waiting
     582             :  * for bgw_restart_time to elapse.  On the other hand, workers with that flag
     583             :  * should be forgotten immediately, since we won't ever restart them.
     584             :  *
     585             :  * This function should only be called from the postmaster.
     586             :  */
     587             : void
     588           8 : ResetBackgroundWorkerCrashTimes(void)
     589             : {
     590             :     slist_mutable_iter iter;
     591             : 
     592          16 :     slist_foreach_modify(iter, &BackgroundWorkerList)
     593             :     {
     594             :         RegisteredBgWorker *rw;
     595             : 
     596           8 :         rw = slist_container(RegisteredBgWorker, rw_lnode, iter.cur);
     597             : 
     598           8 :         if (rw->rw_worker.bgw_restart_time == BGW_NEVER_RESTART)
     599             :         {
     600             :             /*
     601             :              * Workers marked BGW_NEVER_RESTART shouldn't get relaunched after
     602             :              * the crash, so forget about them.  (If we wait until after the
     603             :              * crash to forget about them, and they are parallel workers,
     604             :              * parallel_terminate_count will get incremented after we've
     605             :              * already zeroed parallel_register_count, which would be bad.)
     606             :              */
     607           0 :             ForgetBackgroundWorker(&iter);
     608             :         }
     609             :         else
     610             :         {
     611             :             /*
     612             :              * The accounting which we do via parallel_register_count and
     613             :              * parallel_terminate_count would get messed up if a worker marked
     614             :              * parallel could survive a crash and restart cycle. All such
     615             :              * workers should be marked BGW_NEVER_RESTART, and thus control
     616             :              * should never reach this branch.
     617             :              */
     618             :             Assert((rw->rw_worker.bgw_flags & BGWORKER_CLASS_PARALLEL) == 0);
     619             : 
     620             :             /*
     621             :              * Allow this worker to be restarted immediately after we finish
     622             :              * resetting.
     623             :              */
     624           8 :             rw->rw_crashed_at = 0;
     625             : 
     626             :             /*
     627             :              * If there was anyone waiting for it, they're history.
     628             :              */
     629           8 :             rw->rw_worker.bgw_notify_pid = 0;
     630             :         }
     631             :     }
     632           8 : }
     633             : 
     634             : #ifdef EXEC_BACKEND
     635             : /*
     636             :  * In EXEC_BACKEND mode, workers use this to retrieve their details from
     637             :  * shared memory.
     638             :  */
     639             : BackgroundWorker *
     640             : BackgroundWorkerEntry(int slotno)
     641             : {
     642             :     static BackgroundWorker myEntry;
     643             :     BackgroundWorkerSlot *slot;
     644             : 
     645             :     Assert(slotno < BackgroundWorkerData->total_slots);
     646             :     slot = &BackgroundWorkerData->slot[slotno];
     647             :     Assert(slot->in_use);
     648             : 
     649             :     /* must copy this in case we don't intend to retain shmem access */
     650             :     memcpy(&myEntry, &slot->worker, sizeof myEntry);
     651             :     return &myEntry;
     652             : }
     653             : #endif
     654             : 
     655             : /*
     656             :  * Complain about the BackgroundWorker definition using error level elevel.
     657             :  * Return true if it looks ok, false if not (unless elevel >= ERROR, in
     658             :  * which case we won't return at all in the not-OK case).
     659             :  */
     660             : static bool
     661        4494 : SanityCheckBackgroundWorker(BackgroundWorker *worker, int elevel)
     662             : {
     663             :     /* sanity check for flags */
     664             : 
     665             :     /*
     666             :      * We used to support workers not connected to shared memory, but don't
     667             :      * anymore. Thus this is a required flag now. We're not removing the flag
     668             :      * for compatibility reasons and because the flag still provides some
     669             :      * signal when reading code.
     670             :      */
     671        4494 :     if (!(worker->bgw_flags & BGWORKER_SHMEM_ACCESS))
     672             :     {
     673           0 :         ereport(elevel,
     674             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     675             :                  errmsg("background worker \"%s\": background workers without shared memory access are not supported",
     676             :                         worker->bgw_name)));
     677           0 :         return false;
     678             :     }
     679             : 
     680        4494 :     if (worker->bgw_flags & BGWORKER_BACKEND_DATABASE_CONNECTION)
     681             :     {
     682        4476 :         if (worker->bgw_start_time == BgWorkerStart_PostmasterStart)
     683             :         {
     684           0 :             ereport(elevel,
     685             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     686             :                      errmsg("background worker \"%s\": cannot request database access if starting at postmaster start",
     687             :                             worker->bgw_name)));
     688           0 :             return false;
     689             :         }
     690             : 
     691             :         /* XXX other checks? */
     692             :     }
     693             : 
     694        4494 :     if ((worker->bgw_restart_time < 0 &&
     695        3230 :          worker->bgw_restart_time != BGW_NEVER_RESTART) ||
     696        4494 :         (worker->bgw_restart_time > USECS_PER_DAY / 1000))
     697             :     {
     698           0 :         ereport(elevel,
     699             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     700             :                  errmsg("background worker \"%s\": invalid restart interval",
     701             :                         worker->bgw_name)));
     702           0 :         return false;
     703             :     }
     704             : 
     705             :     /*
     706             :      * Parallel workers may not be configured for restart, because the
     707             :      * parallel_register_count/parallel_terminate_count accounting can't
     708             :      * handle parallel workers lasting through a crash-and-restart cycle.
     709             :      */
     710        4494 :     if (worker->bgw_restart_time != BGW_NEVER_RESTART &&
     711        1264 :         (worker->bgw_flags & BGWORKER_CLASS_PARALLEL) != 0)
     712             :     {
     713           0 :         ereport(elevel,
     714             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     715             :                  errmsg("background worker \"%s\": parallel workers may not be configured for restart",
     716             :                         worker->bgw_name)));
     717           0 :         return false;
     718             :     }
     719             : 
     720             :     /*
     721             :      * If bgw_type is not filled in, use bgw_name.
     722             :      */
     723        4494 :     if (strcmp(worker->bgw_type, "") == 0)
     724           0 :         strcpy(worker->bgw_type, worker->bgw_name);
     725             : 
     726        4494 :     return true;
     727             : }
     728             : 
     729             : /*
     730             :  * Standard SIGTERM handler for background workers
     731             :  */
     732             : static void
     733           0 : bgworker_die(SIGNAL_ARGS)
     734             : {
     735           0 :     sigprocmask(SIG_SETMASK, &BlockSig, NULL);
     736             : 
     737           0 :     ereport(FATAL,
     738             :             (errcode(ERRCODE_ADMIN_SHUTDOWN),
     739             :              errmsg("terminating background worker \"%s\" due to administrator command",
     740             :                     MyBgworkerEntry->bgw_type)));
     741             : }
     742             : 
     743             : /*
     744             :  * Main entry point for background worker processes.
     745             :  */
     746             : void
     747        3946 : BackgroundWorkerMain(void)
     748             : {
     749             :     sigjmp_buf  local_sigjmp_buf;
     750        3946 :     BackgroundWorker *worker = MyBgworkerEntry;
     751             :     bgworker_main_type entrypt;
     752             : 
     753        3946 :     if (worker == NULL)
     754           0 :         elog(FATAL, "unable to find bgworker entry");
     755             : 
     756        3946 :     IsBackgroundWorker = true;
     757             : 
     758        3946 :     MyBackendType = B_BG_WORKER;
     759        3946 :     init_ps_display(worker->bgw_name);
     760             : 
     761        3946 :     SetProcessingMode(InitProcessing);
     762             : 
     763             :     /* Apply PostAuthDelay */
     764        3946 :     if (PostAuthDelay > 0)
     765           0 :         pg_usleep(PostAuthDelay * 1000000L);
     766             : 
     767             :     /*
     768             :      * Set up signal handlers.
     769             :      */
     770        3946 :     if (worker->bgw_flags & BGWORKER_BACKEND_DATABASE_CONNECTION)
     771             :     {
     772             :         /*
     773             :          * SIGINT is used to signal canceling the current action
     774             :          */
     775        3928 :         pqsignal(SIGINT, StatementCancelHandler);
     776        3928 :         pqsignal(SIGUSR1, procsignal_sigusr1_handler);
     777        3928 :         pqsignal(SIGFPE, FloatExceptionHandler);
     778             : 
     779             :         /* XXX Any other handlers needed here? */
     780             :     }
     781             :     else
     782             :     {
     783          18 :         pqsignal(SIGINT, SIG_IGN);
     784          18 :         pqsignal(SIGUSR1, SIG_IGN);
     785          18 :         pqsignal(SIGFPE, SIG_IGN);
     786             :     }
     787        3946 :     pqsignal(SIGTERM, bgworker_die);
     788             :     /* SIGQUIT handler was already set up by InitPostmasterChild */
     789        3946 :     pqsignal(SIGHUP, SIG_IGN);
     790             : 
     791        3946 :     InitializeTimeouts();       /* establishes SIGALRM handler */
     792             : 
     793        3946 :     pqsignal(SIGPIPE, SIG_IGN);
     794        3946 :     pqsignal(SIGUSR2, SIG_IGN);
     795        3946 :     pqsignal(SIGCHLD, SIG_DFL);
     796             : 
     797             :     /*
     798             :      * If an exception is encountered, processing resumes here.
     799             :      *
     800             :      * We just need to clean up, report the error, and go away.
     801             :      */
     802        3946 :     if (sigsetjmp(local_sigjmp_buf, 1) != 0)
     803             :     {
     804             :         /* Since not using PG_TRY, must reset error stack by hand */
     805         136 :         error_context_stack = NULL;
     806             : 
     807             :         /* Prevent interrupts while cleaning up */
     808         136 :         HOLD_INTERRUPTS();
     809             : 
     810             :         /*
     811             :          * sigsetjmp will have blocked all signals, but we may need to accept
     812             :          * signals while communicating with our parallel leader.  Once we've
     813             :          * done HOLD_INTERRUPTS() it should be safe to unblock signals.
     814             :          */
     815         136 :         BackgroundWorkerUnblockSignals();
     816             : 
     817             :         /* Report the error to the parallel leader and the server log */
     818         136 :         EmitErrorReport();
     819             : 
     820             :         /*
     821             :          * Do we need more cleanup here?  For shmem-connected bgworkers, we
     822             :          * will call InitProcess below, which will install ProcKill as exit
     823             :          * callback.  That will take care of releasing locks, etc.
     824             :          */
     825             : 
     826             :         /* and go away */
     827         136 :         proc_exit(1);
     828             :     }
     829             : 
     830             :     /* We can now handle ereport(ERROR) */
     831        3946 :     PG_exception_stack = &local_sigjmp_buf;
     832             : 
     833             :     /*
     834             :      * Create a per-backend PGPROC struct in shared memory, except in the
     835             :      * EXEC_BACKEND case where this was done in SubPostmasterMain. We must do
     836             :      * this before we can use LWLocks (and in the EXEC_BACKEND case we already
     837             :      * had to do some stuff with LWLocks).
     838             :      */
     839             : #ifndef EXEC_BACKEND
     840        3946 :     InitProcess();
     841             : #endif
     842             : 
     843             :     /*
     844             :      * Early initialization.
     845             :      */
     846        3946 :     BaseInit();
     847             : 
     848             :     /*
     849             :      * Look up the entry point function, loading its library if necessary.
     850             :      */
     851        7892 :     entrypt = LookupBackgroundWorkerFunction(worker->bgw_library_name,
     852        3946 :                                              worker->bgw_function_name);
     853             : 
     854             :     /*
     855             :      * Note that in normal processes, we would call InitPostgres here.  For a
     856             :      * worker, however, we don't know what database to connect to, yet; so we
     857             :      * need to wait until the user code does it via
     858             :      * BackgroundWorkerInitializeConnection().
     859             :      */
     860             : 
     861             :     /*
     862             :      * Now invoke the user-defined worker code
     863             :      */
     864        3946 :     entrypt(worker->bgw_main_arg);
     865             : 
     866             :     /* ... and if it returns, we're done */
     867        2594 :     proc_exit(0);
     868             : }
     869             : 
     870             : /*
     871             :  * Register a new static background worker.
     872             :  *
     873             :  * This can only be called directly from postmaster or in the _PG_init
     874             :  * function of a module library that's loaded by shared_preload_libraries;
     875             :  * otherwise it will have no effect.
     876             :  */
     877             : void
     878        1270 : RegisterBackgroundWorker(BackgroundWorker *worker)
     879             : {
     880             :     RegisteredBgWorker *rw;
     881             :     static int  numworkers = 0;
     882             : 
     883             :     /*
     884             :      * Static background workers can only be registered in the postmaster
     885             :      * process.
     886             :      */
     887        1270 :     if (IsUnderPostmaster || !IsPostmasterEnvironment)
     888             :     {
     889             :         /*
     890             :          * In EXEC_BACKEND or single-user mode, we process
     891             :          * shared_preload_libraries in backend processes too.  We cannot
     892             :          * register static background workers at that stage, but many
     893             :          * libraries' _PG_init() functions don't distinguish whether they're
     894             :          * being loaded in the postmaster or in a backend, they just check
     895             :          * process_shared_preload_libraries_in_progress.  It's a bit sloppy,
     896             :          * but for historical reasons we tolerate it.  In EXEC_BACKEND mode,
     897             :          * the background workers should already have been registered when the
     898             :          * library was loaded in postmaster.
     899             :          */
     900           0 :         if (process_shared_preload_libraries_in_progress)
     901           0 :             return;
     902           0 :         ereport(LOG,
     903             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     904             :                  errmsg("background worker \"%s\": must be registered in shared_preload_libraries",
     905             :                         worker->bgw_name)));
     906           0 :         return;
     907             :     }
     908             : 
     909             :     /*
     910             :      * Cannot register static background workers after calling
     911             :      * BackgroundWorkerShmemInit().
     912             :      */
     913        1270 :     if (BackgroundWorkerData != NULL)
     914           0 :         elog(ERROR, "cannot register background worker \"%s\" after shmem init",
     915             :              worker->bgw_name);
     916             : 
     917        1270 :     ereport(DEBUG1,
     918             :             (errmsg_internal("registering background worker \"%s\"", worker->bgw_name)));
     919             : 
     920        1270 :     if (!SanityCheckBackgroundWorker(worker, LOG))
     921           0 :         return;
     922             : 
     923        1270 :     if (worker->bgw_notify_pid != 0)
     924             :     {
     925           0 :         ereport(LOG,
     926             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     927             :                  errmsg("background worker \"%s\": only dynamic background workers can request notification",
     928             :                         worker->bgw_name)));
     929           0 :         return;
     930             :     }
     931             : 
     932             :     /*
     933             :      * Enforce maximum number of workers.  Note this is overly restrictive: we
     934             :      * could allow more non-shmem-connected workers, because these don't count
     935             :      * towards the MAX_BACKENDS limit elsewhere.  For now, it doesn't seem
     936             :      * important to relax this restriction.
     937             :      */
     938        1270 :     if (++numworkers > max_worker_processes)
     939             :     {
     940           0 :         ereport(LOG,
     941             :                 (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
     942             :                  errmsg("too many background workers"),
     943             :                  errdetail_plural("Up to %d background worker can be registered with the current settings.",
     944             :                                   "Up to %d background workers can be registered with the current settings.",
     945             :                                   max_worker_processes,
     946             :                                   max_worker_processes),
     947             :                  errhint("Consider increasing the configuration parameter max_worker_processes.")));
     948           0 :         return;
     949             :     }
     950             : 
     951             :     /*
     952             :      * Copy the registration data into the registered workers list.
     953             :      */
     954        1270 :     rw = MemoryContextAllocExtended(PostmasterContext,
     955             :                                     sizeof(RegisteredBgWorker),
     956             :                                     MCXT_ALLOC_NO_OOM);
     957        1270 :     if (rw == NULL)
     958             :     {
     959           0 :         ereport(LOG,
     960             :                 (errcode(ERRCODE_OUT_OF_MEMORY),
     961             :                  errmsg("out of memory")));
     962           0 :         return;
     963             :     }
     964             : 
     965        1270 :     rw->rw_worker = *worker;
     966        1270 :     rw->rw_backend = NULL;
     967        1270 :     rw->rw_pid = 0;
     968        1270 :     rw->rw_child_slot = 0;
     969        1270 :     rw->rw_crashed_at = 0;
     970        1270 :     rw->rw_terminate = false;
     971             : 
     972        1270 :     slist_push_head(&BackgroundWorkerList, &rw->rw_lnode);
     973             : }
     974             : 
     975             : /*
     976             :  * Register a new background worker from a regular backend.
     977             :  *
     978             :  * Returns true on success and false on failure.  Failure typically indicates
     979             :  * that no background worker slots are currently available.
     980             :  *
     981             :  * If handle != NULL, we'll set *handle to a pointer that can subsequently
     982             :  * be used as an argument to GetBackgroundWorkerPid().  The caller can
     983             :  * free this pointer using pfree(), if desired.
     984             :  */
     985             : bool
     986        3224 : RegisterDynamicBackgroundWorker(BackgroundWorker *worker,
     987             :                                 BackgroundWorkerHandle **handle)
     988             : {
     989             :     int         slotno;
     990        3224 :     bool        success = false;
     991             :     bool        parallel;
     992        3224 :     uint64      generation = 0;
     993             : 
     994             :     /*
     995             :      * We can't register dynamic background workers from the postmaster. If
     996             :      * this is a standalone backend, we're the only process and can't start
     997             :      * any more.  In a multi-process environment, it might be theoretically
     998             :      * possible, but we don't currently support it due to locking
     999             :      * considerations; see comments on the BackgroundWorkerSlot data
    1000             :      * structure.
    1001             :      */
    1002        3224 :     if (!IsUnderPostmaster)
    1003           0 :         return false;
    1004             : 
    1005        3224 :     if (!SanityCheckBackgroundWorker(worker, ERROR))
    1006           0 :         return false;
    1007             : 
    1008        3224 :     parallel = (worker->bgw_flags & BGWORKER_CLASS_PARALLEL) != 0;
    1009             : 
    1010        3224 :     LWLockAcquire(BackgroundWorkerLock, LW_EXCLUSIVE);
    1011             : 
    1012             :     /*
    1013             :      * If this is a parallel worker, check whether there are already too many
    1014             :      * parallel workers; if so, don't register another one.  Our view of
    1015             :      * parallel_terminate_count may be slightly stale, but that doesn't really
    1016             :      * matter: we would have gotten the same result if we'd arrived here
    1017             :      * slightly earlier anyway.  There's no help for it, either, since the
    1018             :      * postmaster must not take locks; a memory barrier wouldn't guarantee
    1019             :      * anything useful.
    1020             :      */
    1021        3224 :     if (parallel && (BackgroundWorkerData->parallel_register_count -
    1022        2614 :                      BackgroundWorkerData->parallel_terminate_count) >=
    1023             :         max_parallel_workers)
    1024             :     {
    1025             :         Assert(BackgroundWorkerData->parallel_register_count -
    1026             :                BackgroundWorkerData->parallel_terminate_count <=
    1027             :                MAX_PARALLEL_WORKER_LIMIT);
    1028          18 :         LWLockRelease(BackgroundWorkerLock);
    1029          18 :         return false;
    1030             :     }
    1031             : 
    1032             :     /*
    1033             :      * Look for an unused slot.  If we find one, grab it.
    1034             :      */
    1035        9940 :     for (slotno = 0; slotno < BackgroundWorkerData->total_slots; ++slotno)
    1036             :     {
    1037        9938 :         BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
    1038             : 
    1039        9938 :         if (!slot->in_use)
    1040             :         {
    1041        3204 :             memcpy(&slot->worker, worker, sizeof(BackgroundWorker));
    1042        3204 :             slot->pid = InvalidPid; /* indicates not started yet */
    1043        3204 :             slot->generation++;
    1044        3204 :             slot->terminate = false;
    1045        3204 :             generation = slot->generation;
    1046        3204 :             if (parallel)
    1047        2594 :                 BackgroundWorkerData->parallel_register_count++;
    1048             : 
    1049             :             /*
    1050             :              * Make sure postmaster doesn't see the slot as in use before it
    1051             :              * sees the new contents.
    1052             :              */
    1053        3204 :             pg_write_barrier();
    1054             : 
    1055        3204 :             slot->in_use = true;
    1056        3204 :             success = true;
    1057        3204 :             break;
    1058             :         }
    1059             :     }
    1060             : 
    1061        3206 :     LWLockRelease(BackgroundWorkerLock);
    1062             : 
    1063             :     /* If we found a slot, tell the postmaster to notice the change. */
    1064        3206 :     if (success)
    1065        3204 :         SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE);
    1066             : 
    1067             :     /*
    1068             :      * If we found a slot and the user has provided a handle, initialize it.
    1069             :      */
    1070        3206 :     if (success && handle)
    1071             :     {
    1072        3204 :         *handle = palloc(sizeof(BackgroundWorkerHandle));
    1073        3204 :         (*handle)->slot = slotno;
    1074        3204 :         (*handle)->generation = generation;
    1075             :     }
    1076             : 
    1077        3206 :     return success;
    1078             : }
    1079             : 
    1080             : /*
    1081             :  * Get the PID of a dynamically-registered background worker.
    1082             :  *
    1083             :  * If the worker is determined to be running, the return value will be
    1084             :  * BGWH_STARTED and *pidp will get the PID of the worker process.  If the
    1085             :  * postmaster has not yet attempted to start the worker, the return value will
    1086             :  * be BGWH_NOT_YET_STARTED.  Otherwise, the return value is BGWH_STOPPED.
    1087             :  *
    1088             :  * BGWH_STOPPED can indicate either that the worker is temporarily stopped
    1089             :  * (because it is configured for automatic restart and exited non-zero),
    1090             :  * or that the worker is permanently stopped (because it exited with exit
    1091             :  * code 0, or was not configured for automatic restart), or even that the
    1092             :  * worker was unregistered without ever starting (either because startup
    1093             :  * failed and the worker is not configured for automatic restart, or because
    1094             :  * TerminateBackgroundWorker was used before the worker was successfully
    1095             :  * started).
    1096             :  */
    1097             : BgwHandleStatus
    1098    16819046 : GetBackgroundWorkerPid(BackgroundWorkerHandle *handle, pid_t *pidp)
    1099             : {
    1100             :     BackgroundWorkerSlot *slot;
    1101             :     pid_t       pid;
    1102             : 
    1103             :     Assert(handle->slot < max_worker_processes);
    1104    16819046 :     slot = &BackgroundWorkerData->slot[handle->slot];
    1105             : 
    1106             :     /*
    1107             :      * We could probably arrange to synchronize access to data using memory
    1108             :      * barriers only, but for now, let's just keep it simple and grab the
    1109             :      * lock.  It seems unlikely that there will be enough traffic here to
    1110             :      * result in meaningful contention.
    1111             :      */
    1112    16819046 :     LWLockAcquire(BackgroundWorkerLock, LW_SHARED);
    1113             : 
    1114             :     /*
    1115             :      * The generation number can't be concurrently changed while we hold the
    1116             :      * lock.  The pid, which is updated by the postmaster, can change at any
    1117             :      * time, but we assume such changes are atomic.  So the value we read
    1118             :      * won't be garbage, but it might be out of date by the time the caller
    1119             :      * examines it (but that's unavoidable anyway).
    1120             :      *
    1121             :      * The in_use flag could be in the process of changing from true to false,
    1122             :      * but if it is already false then it can't change further.
    1123             :      */
    1124    16819046 :     if (handle->generation != slot->generation || !slot->in_use)
    1125        2596 :         pid = 0;
    1126             :     else
    1127    16816450 :         pid = slot->pid;
    1128             : 
    1129             :     /* All done. */
    1130    16819046 :     LWLockRelease(BackgroundWorkerLock);
    1131             : 
    1132    16819046 :     if (pid == 0)
    1133        2596 :         return BGWH_STOPPED;
    1134    16816450 :     else if (pid == InvalidPid)
    1135     5108798 :         return BGWH_NOT_YET_STARTED;
    1136    11707652 :     *pidp = pid;
    1137    11707652 :     return BGWH_STARTED;
    1138             : }
    1139             : 
    1140             : /*
    1141             :  * Wait for a background worker to start up.
    1142             :  *
    1143             :  * This is like GetBackgroundWorkerPid(), except that if the worker has not
    1144             :  * yet started, we wait for it to do so; thus, BGWH_NOT_YET_STARTED is never
    1145             :  * returned.  However, if the postmaster has died, we give up and return
    1146             :  * BGWH_POSTMASTER_DIED, since it that case we know that startup will not
    1147             :  * take place.
    1148             :  *
    1149             :  * The caller *must* have set our PID as the worker's bgw_notify_pid,
    1150             :  * else we will not be awoken promptly when the worker's state changes.
    1151             :  */
    1152             : BgwHandleStatus
    1153          38 : WaitForBackgroundWorkerStartup(BackgroundWorkerHandle *handle, pid_t *pidp)
    1154             : {
    1155             :     BgwHandleStatus status;
    1156             :     int         rc;
    1157             : 
    1158             :     for (;;)
    1159          24 :     {
    1160             :         pid_t       pid;
    1161             : 
    1162          38 :         CHECK_FOR_INTERRUPTS();
    1163             : 
    1164          38 :         status = GetBackgroundWorkerPid(handle, &pid);
    1165          38 :         if (status == BGWH_STARTED)
    1166          14 :             *pidp = pid;
    1167          38 :         if (status != BGWH_NOT_YET_STARTED)
    1168          14 :             break;
    1169             : 
    1170          24 :         rc = WaitLatch(MyLatch,
    1171             :                        WL_LATCH_SET | WL_POSTMASTER_DEATH, 0,
    1172             :                        WAIT_EVENT_BGWORKER_STARTUP);
    1173             : 
    1174          24 :         if (rc & WL_POSTMASTER_DEATH)
    1175             :         {
    1176           0 :             status = BGWH_POSTMASTER_DIED;
    1177           0 :             break;
    1178             :         }
    1179             : 
    1180          24 :         ResetLatch(MyLatch);
    1181             :     }
    1182             : 
    1183          14 :     return status;
    1184             : }
    1185             : 
    1186             : /*
    1187             :  * Wait for a background worker to stop.
    1188             :  *
    1189             :  * If the worker hasn't yet started, or is running, we wait for it to stop
    1190             :  * and then return BGWH_STOPPED.  However, if the postmaster has died, we give
    1191             :  * up and return BGWH_POSTMASTER_DIED, because it's the postmaster that
    1192             :  * notifies us when a worker's state changes.
    1193             :  *
    1194             :  * The caller *must* have set our PID as the worker's bgw_notify_pid,
    1195             :  * else we will not be awoken promptly when the worker's state changes.
    1196             :  */
    1197             : BgwHandleStatus
    1198        5124 : WaitForBackgroundWorkerShutdown(BackgroundWorkerHandle *handle)
    1199             : {
    1200             :     BgwHandleStatus status;
    1201             :     int         rc;
    1202             : 
    1203             :     for (;;)
    1204        2528 :     {
    1205             :         pid_t       pid;
    1206             : 
    1207        5124 :         CHECK_FOR_INTERRUPTS();
    1208             : 
    1209        5124 :         status = GetBackgroundWorkerPid(handle, &pid);
    1210        5124 :         if (status == BGWH_STOPPED)
    1211        2596 :             break;
    1212             : 
    1213        2528 :         rc = WaitLatch(MyLatch,
    1214             :                        WL_LATCH_SET | WL_POSTMASTER_DEATH, 0,
    1215             :                        WAIT_EVENT_BGWORKER_SHUTDOWN);
    1216             : 
    1217        2528 :         if (rc & WL_POSTMASTER_DEATH)
    1218             :         {
    1219           0 :             status = BGWH_POSTMASTER_DIED;
    1220           0 :             break;
    1221             :         }
    1222             : 
    1223        2528 :         ResetLatch(MyLatch);
    1224             :     }
    1225             : 
    1226        2596 :     return status;
    1227             : }
    1228             : 
    1229             : /*
    1230             :  * Instruct the postmaster to terminate a background worker.
    1231             :  *
    1232             :  * Note that it's safe to do this without regard to whether the worker is
    1233             :  * still running, or even if the worker may already have exited and been
    1234             :  * unregistered.
    1235             :  */
    1236             : void
    1237           6 : TerminateBackgroundWorker(BackgroundWorkerHandle *handle)
    1238             : {
    1239             :     BackgroundWorkerSlot *slot;
    1240           6 :     bool        signal_postmaster = false;
    1241             : 
    1242             :     Assert(handle->slot < max_worker_processes);
    1243           6 :     slot = &BackgroundWorkerData->slot[handle->slot];
    1244             : 
    1245             :     /* Set terminate flag in shared memory, unless slot has been reused. */
    1246           6 :     LWLockAcquire(BackgroundWorkerLock, LW_EXCLUSIVE);
    1247           6 :     if (handle->generation == slot->generation)
    1248             :     {
    1249           6 :         slot->terminate = true;
    1250           6 :         signal_postmaster = true;
    1251             :     }
    1252           6 :     LWLockRelease(BackgroundWorkerLock);
    1253             : 
    1254             :     /* Make sure the postmaster notices the change to shared memory. */
    1255           6 :     if (signal_postmaster)
    1256           6 :         SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE);
    1257           6 : }
    1258             : 
    1259             : /*
    1260             :  * Look up (and possibly load) a bgworker entry point function.
    1261             :  *
    1262             :  * For functions contained in the core code, we use library name "postgres"
    1263             :  * and consult the InternalBGWorkers array.  External functions are
    1264             :  * looked up, and loaded if necessary, using load_external_function().
    1265             :  *
    1266             :  * The point of this is to pass function names as strings across process
    1267             :  * boundaries.  We can't pass actual function addresses because of the
    1268             :  * possibility that the function has been loaded at a different address
    1269             :  * in a different process.  This is obviously a hazard for functions in
    1270             :  * loadable libraries, but it can happen even for functions in the core code
    1271             :  * on platforms using EXEC_BACKEND (e.g., Windows).
    1272             :  *
    1273             :  * At some point it might be worthwhile to get rid of InternalBGWorkers[]
    1274             :  * in favor of applying load_external_function() for core functions too;
    1275             :  * but that raises portability issues that are not worth addressing now.
    1276             :  */
    1277             : static bgworker_main_type
    1278        3946 : LookupBackgroundWorkerFunction(const char *libraryname, const char *funcname)
    1279             : {
    1280             :     /*
    1281             :      * If the function is to be loaded from postgres itself, search the
    1282             :      * InternalBGWorkers array.
    1283             :      */
    1284        3946 :     if (strcmp(libraryname, "postgres") == 0)
    1285             :     {
    1286             :         int         i;
    1287             : 
    1288        6604 :         for (i = 0; i < lengthof(InternalBGWorkers); i++)
    1289             :         {
    1290        6604 :             if (strcmp(InternalBGWorkers[i].fn_name, funcname) == 0)
    1291        3920 :                 return InternalBGWorkers[i].fn_addr;
    1292             :         }
    1293             : 
    1294             :         /* We can only reach this by programming error. */
    1295           0 :         elog(ERROR, "internal function \"%s\" not found", funcname);
    1296             :     }
    1297             : 
    1298             :     /* Otherwise load from external library. */
    1299          26 :     return (bgworker_main_type)
    1300          26 :         load_external_function(libraryname, funcname, true, NULL);
    1301             : }
    1302             : 
    1303             : /*
    1304             :  * Given a PID, get the bgw_type of the background worker.  Returns NULL if
    1305             :  * not a valid background worker.
    1306             :  *
    1307             :  * The return value is in static memory belonging to this function, so it has
    1308             :  * to be used before calling this function again.  This is so that the caller
    1309             :  * doesn't have to worry about the background worker locking protocol.
    1310             :  */
    1311             : const char *
    1312        1220 : GetBackgroundWorkerTypeByPid(pid_t pid)
    1313             : {
    1314             :     int         slotno;
    1315        1220 :     bool        found = false;
    1316             :     static char result[BGW_MAXLEN];
    1317             : 
    1318        1220 :     LWLockAcquire(BackgroundWorkerLock, LW_SHARED);
    1319             : 
    1320        1390 :     for (slotno = 0; slotno < BackgroundWorkerData->total_slots; slotno++)
    1321             :     {
    1322        1390 :         BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
    1323             : 
    1324        1390 :         if (slot->pid > 0 && slot->pid == pid)
    1325             :         {
    1326        1220 :             strcpy(result, slot->worker.bgw_type);
    1327        1220 :             found = true;
    1328        1220 :             break;
    1329             :         }
    1330             :     }
    1331             : 
    1332        1220 :     LWLockRelease(BackgroundWorkerLock);
    1333             : 
    1334        1220 :     if (!found)
    1335           0 :         return NULL;
    1336             : 
    1337        1220 :     return result;
    1338             : }

Generated by: LCOV version 1.14