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

Generated by: LCOV version 1.13