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

Generated by: LCOV version 1.16