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

Generated by: LCOV version 1.11