From 090d0f2050647958865cb495dff74af7257d2bb4 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Wed, 28 Aug 2013 14:08:13 -0400 Subject: [PATCH] Allow discovery of whether a dynamic background worker is running. Using the infrastructure provided by this patch, it's possible either to wait for the startup of a dynamically-registered background worker, or to poll the status of such a worker without waiting. In either case, the current PID of the worker process can also be obtained. As usual, worker_spi is updated to demonstrate the new functionality. Patch by me. Review by Andres Freund. --- contrib/worker_spi/worker_spi--1.0.sql | 2 +- contrib/worker_spi/worker_spi.c | 24 ++- doc/src/sgml/bgworker.sgml | 54 ++++- src/backend/commands/async.c | 2 - src/backend/postmaster/bgworker.c | 206 +++++++++++++++++++- src/backend/postmaster/postmaster.c | 52 +++++ src/backend/storage/ipc/procsignal.c | 12 ++ src/include/miscadmin.h | 2 + src/include/postmaster/bgworker.h | 21 +- src/include/postmaster/bgworker_internals.h | 2 + src/include/postmaster/postmaster.h | 1 + src/include/storage/procsignal.h | 1 + 12 files changed, 367 insertions(+), 12 deletions(-) diff --git a/contrib/worker_spi/worker_spi--1.0.sql b/contrib/worker_spi/worker_spi--1.0.sql index a56b42c10e..09b7799f2c 100644 --- a/contrib/worker_spi/worker_spi--1.0.sql +++ b/contrib/worker_spi/worker_spi--1.0.sql @@ -4,6 +4,6 @@ \echo Use "CREATE EXTENSION worker_spi" to load this file. \quit CREATE FUNCTION worker_spi_launch(pg_catalog.int4) -RETURNS pg_catalog.bool STRICT +RETURNS pg_catalog.int4 STRICT AS 'MODULE_PATHNAME' LANGUAGE C; diff --git a/contrib/worker_spi/worker_spi.c b/contrib/worker_spi/worker_spi.c index 14b5045caa..8aec9b2199 100644 --- a/contrib/worker_spi/worker_spi.c +++ b/contrib/worker_spi/worker_spi.c @@ -365,6 +365,9 @@ worker_spi_launch(PG_FUNCTION_ARGS) { int32 i = PG_GETARG_INT32(0); BackgroundWorker worker; + BackgroundWorkerHandle *handle; + BgwHandleStatus status; + pid_t pid; worker.bgw_flags = BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION; @@ -375,6 +378,25 @@ worker_spi_launch(PG_FUNCTION_ARGS) sprintf(worker.bgw_function_name, "worker_spi_main"); snprintf(worker.bgw_name, BGW_MAXLEN, "worker %d", i); worker.bgw_main_arg = Int32GetDatum(i); + /* set bgw_notify_pid so that we can use WaitForBackgroundWorkerStartup */ + worker.bgw_notify_pid = MyProcPid; - PG_RETURN_BOOL(RegisterDynamicBackgroundWorker(&worker)); + if (!RegisterDynamicBackgroundWorker(&worker, &handle)) + PG_RETURN_NULL(); + + status = WaitForBackgroundWorkerStartup(handle, &pid); + + if (status == BGWH_STOPPED) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_RESOURCES), + errmsg("could not start background process"), + errhint("More details may be available in the server log."))); + if (status == BGWH_POSTMASTER_DIED) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_RESOURCES), + errmsg("cannot start background processes without postmaster"), + errhint("Kill all remaining database processes and restart the database."))); + Assert(status == BGWH_STARTED); + + PG_RETURN_INT32(pid); } diff --git a/doc/src/sgml/bgworker.sgml b/doc/src/sgml/bgworker.sgml index 268e1cd215..102d46372b 100644 --- a/doc/src/sgml/bgworker.sgml +++ b/doc/src/sgml/bgworker.sgml @@ -37,11 +37,11 @@ RegisterBackgroundWorker(BackgroundWorker *worker) from its _PG_init(). Background workers can also be started after the system is up and running by calling the function - RegisterDynamicBackgroundWorker(BackgroundWorker - *worker). Unlike RegisterBackgroundWorker, which can - only be called from within the postmaster, - RegisterDynamicBackgroundWorker must be called from - a regular backend. + RegisterDynamicBackgroundWorker(BackgroundWorker + *worker, BackgroundWorkerHandle **handle). Unlike + RegisterBackgroundWorker, which can only be called from within + the postmaster, RegisterDynamicBackgroundWorker must be + called from a regular backend. @@ -58,6 +58,7 @@ typedef struct BackgroundWorker char bgw_library_name[BGW_MAXLEN]; /* only if bgw_main is NULL */ char bgw_function_name[BGW_MAXLEN]; /* only if bgw_main is NULL */ Datum bgw_main_arg; + int bgw_notify_pid; } BackgroundWorker; @@ -135,6 +136,15 @@ typedef struct BackgroundWorker bgw_main is NULL. + + bgw_notify_pid is the PID of a PostgreSQL + backend process to which the postmaster should send SIGUSR1 + when the process is started or exits. It should be 0 for workers registered + at postmaster startup time, or when the backend registering the worker does + not wish to wait for the worker to start up. Otherwise, it should be + initialized to MyProcPid. + + Once running, the process can connect to a database by calling BackgroundWorkerInitializeConnection(char *dbname, char *username). This allows the process to run transactions and queries using the @@ -165,6 +175,40 @@ typedef struct BackgroundWorker postgres itself has terminated. + + When a background worker is registered using the + RegisterDynamicBackgroundWorker function, it is + possible for the backend performing the registration to obtain information + the status of the worker. Backends wishing to do this should pass the + address of a BackgroundWorkerHandle * as the second argument + to RegisterDynamicBackgroundWorker. If the worker + is successfully registered, this pointer will be initialized with an + opaque handle that can subsequently be passed to + GetBackgroundWorkerPid(BackgroundWorkerHandle *, pid_t *). + This function can be used to poll the status of the worker: a return + value of BGWH_NOT_YET_STARTED indicates that the worker has not + yet been started by the postmaster; BGWH_STOPPED + indicates that it has been started but is no longer running; and + BGWH_STARTED indicates that it is currently running. + In this last case, the PID will also be returned via the second argument. + + + + In some cases, a process which registers a background worker may wish to + wait for the worker to start up. This can be accomplished by initializing + bgw_notify_pid to MyProcPid and + then passing the BackgroundWorkerHandle * obtained at + registration time to + WaitForBackgroundWorkerStartup(BackgroundWorkerHandle + *handle, pid_t *) function. + This function will block until the postmaster has attempted to start the + background worker, or until the postmaster dies. If the background runner + is running, the return value will BGWH_STARTED, and + the PID will be written to the provided address. Otherwise, the return + value will be BGWH_STOPPED or + BGWH_POSTMASTER_DIED. + + The worker_spi contrib module contains a working example, which demonstrates some useful techniques. diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index f7ebd1a650..6414291ef7 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -207,8 +207,6 @@ typedef struct QueueBackendStatus QueuePosition pos; /* backend has read queue up to here */ } QueueBackendStatus; -#define InvalidPid (-1) - /* * Shared memory state for LISTEN/NOTIFY (excluding its SLRU stuff) * diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index fc73030214..25e61568bd 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -18,6 +18,7 @@ #include "miscadmin.h" #include "libpq/pqsignal.h" #include "postmaster/bgworker_internals.h" +#include "postmaster/postmaster.h" #include "storage/barrier.h" #include "storage/ipc.h" #include "storage/latch.h" @@ -66,6 +67,8 @@ slist_head BackgroundWorkerList = SLIST_STATIC_INIT(BackgroundWorkerList); typedef struct BackgroundWorkerSlot { bool in_use; + pid_t pid; /* InvalidPid = not started yet; 0 = dead */ + uint64 generation; /* incremented when slot is recycled */ BackgroundWorker worker; } BackgroundWorkerSlot; @@ -75,6 +78,12 @@ typedef struct BackgroundWorkerArray BackgroundWorkerSlot slot[FLEXIBLE_ARRAY_MEMBER]; } BackgroundWorkerArray; +struct BackgroundWorkerHandle +{ + int slot; + uint64 generation; +}; + BackgroundWorkerArray *BackgroundWorkerData; /* @@ -125,7 +134,10 @@ BackgroundWorkerShmemInit(void) rw = slist_container(RegisteredBgWorker, rw_lnode, siter.cur); Assert(slotno < max_worker_processes); slot->in_use = true; + slot->pid = InvalidPid; + slot->generation = 0; rw->rw_shmem_slot = slotno; + rw->rw_worker.bgw_notify_pid = 0; /* might be reinit after crash */ memcpy(&slot->worker, &rw->rw_worker, sizeof(BackgroundWorker)); ++slotno; } @@ -244,7 +256,7 @@ BackgroundWorkerStateChange(void) slot->worker.bgw_function_name, BGW_MAXLEN); /* - * Copy remaining fields. + * Copy various fixed-size fields. * * flags, start_time, and restart_time are examined by the * postmaster, but nothing too bad will happen if they are @@ -257,6 +269,23 @@ BackgroundWorkerStateChange(void) rw->rw_worker.bgw_main = slot->worker.bgw_main; rw->rw_worker.bgw_main_arg = slot->worker.bgw_main_arg; + /* + * Copy the PID to be notified about state changes, but only if + * the postmaster knows about a backend with that PID. It isn't + * an error if the postmaster doesn't know about the PID, because + * the backend that requested the worker could have died (or been + * killed) just after doing so. Nonetheless, at least until we get + * some experience with how this plays out in the wild, log a message + * at a relative high debug level. + */ + rw->rw_worker.bgw_notify_pid = slot->worker.bgw_notify_pid; + if (!PostmasterMarkPIDForWorkerNotify(rw->rw_worker.bgw_notify_pid)) + { + elog(DEBUG1, "worker notification PID %u is not valid", + rw->rw_worker.bgw_notify_pid); + rw->rw_worker.bgw_notify_pid = 0; + } + /* Initialize postmaster bookkeeping. */ rw->rw_backend = NULL; rw->rw_pid = 0; @@ -302,6 +331,44 @@ ForgetBackgroundWorker(slist_mutable_iter *cur) free(rw); } +/* + * Report the PID of a newly-launched background worker in shared memory. + * + * This function should only be called from the postmaster. + */ +void +ReportBackgroundWorkerPID(RegisteredBgWorker *rw) +{ + BackgroundWorkerSlot *slot; + + Assert(rw->rw_shmem_slot < max_worker_processes); + slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot]; + slot->pid = rw->rw_pid; + + if (rw->rw_worker.bgw_notify_pid != 0) + kill(rw->rw_worker.bgw_notify_pid, SIGUSR1); +} + +/* + * Cancel SIGUSR1 notifications for a PID belonging to an exiting backend. + * + * This function should only be called from the postmaster. + */ +void +BackgroundWorkerStopNotifications(pid_t pid) +{ + slist_iter siter; + + slist_foreach(siter, &BackgroundWorkerList) + { + RegisteredBgWorker *rw; + + rw = slist_container(RegisteredBgWorker, rw_lnode, siter.cur); + if (rw->rw_worker.bgw_notify_pid == pid) + rw->rw_worker.bgw_notify_pid = 0; + } +} + #ifdef EXEC_BACKEND /* * In EXEC_BACKEND mode, workers use this to retrieve their details from @@ -602,6 +669,15 @@ RegisterBackgroundWorker(BackgroundWorker *worker) if (!SanityCheckBackgroundWorker(worker, LOG)) return; + if (worker->bgw_notify_pid != 0) + { + ereport(LOG, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("background worker \"%s\": only dynamic background workers can request notification", + worker->bgw_name))); + return; + } + /* * Enforce maximum number of workers. Note this is overly restrictive: we * could allow more non-shmem-connected workers, because these don't count @@ -647,12 +723,18 @@ RegisterBackgroundWorker(BackgroundWorker *worker) * * Returns true on success and false on failure. Failure typically indicates * that no background worker slots are currently available. + * + * If handle != NULL, we'll set *handle to a pointer that can subsequently + * be used as an argument to GetBackgroundWorkerPid(). The caller can + * free this pointer using pfree(), if desired. */ bool -RegisterDynamicBackgroundWorker(BackgroundWorker *worker) +RegisterDynamicBackgroundWorker(BackgroundWorker *worker, + BackgroundWorkerHandle **handle) { int slotno; bool success = false; + uint64 generation; /* * We can't register dynamic background workers from the postmaster. @@ -680,6 +762,9 @@ RegisterDynamicBackgroundWorker(BackgroundWorker *worker) if (!slot->in_use) { memcpy(&slot->worker, worker, sizeof(BackgroundWorker)); + slot->pid = InvalidPid; /* indicates not started yet */ + slot->generation++; + generation = slot->generation; /* * Make sure postmaster doesn't see the slot as in use before @@ -699,5 +784,122 @@ RegisterDynamicBackgroundWorker(BackgroundWorker *worker) if (success) SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE); + /* + * If we found a slot and the user has provided a handle, initialize it. + */ + if (success && handle) + { + *handle = palloc(sizeof(BackgroundWorkerHandle)); + (*handle)->slot = slotno; + (*handle)->generation = generation; + } + return success; } + +/* + * Get the PID of a dynamically-registered background worker. + * + * If the worker is determined to be running, the return value will be + * BGWH_STARTED and *pidp will get the PID of the worker process. + * Otherwise, the return value will be BGWH_NOT_YET_STARTED if the worker + * hasn't been started yet, and BGWH_STOPPED if the worker was previously + * running but is no longer. + * + * In the latter case, the worker may be stopped temporarily (if it is + * configured for automatic restart, or if it exited with code 0) or gone + * for good (if it is configured not to restart and exited with code 1). + */ +BgwHandleStatus +GetBackgroundWorkerPid(BackgroundWorkerHandle *handle, pid_t *pidp) +{ + BackgroundWorkerSlot *slot; + pid_t pid; + + Assert(handle->slot < max_worker_processes); + slot = &BackgroundWorkerData->slot[handle->slot]; + + /* + * We could probably arrange to synchronize access to data using + * memory barriers only, but for now, let's just keep it simple and + * grab the lock. It seems unlikely that there will be enough traffic + * here to result in meaningful contention. + */ + LWLockAcquire(BackgroundWorkerLock, LW_SHARED); + + /* + * The generation number can't be concurrently changed while we hold the + * lock. The pid, which is updated by the postmaster, can change at any + * time, but we assume such changes are atomic. So the value we read + * won't be garbage, but it might be out of date by the time the caller + * examines it (but that's unavoidable anyway). + */ + if (handle->generation != slot->generation) + pid = 0; + else + pid = slot->pid; + + /* All done. */ + LWLockRelease(BackgroundWorkerLock); + + if (pid == 0) + return BGWH_STOPPED; + else if (pid == InvalidPid) + return BGWH_NOT_YET_STARTED; + *pidp = pid; + return BGWH_STARTED; +} + +/* + * Wait for a background worker to start up. + * + * This is like GetBackgroundWorkerPid(), except that if the worker has not + * yet started, we wait for it to do so; thus, BGWH_NOT_YET_STARTED is never + * returned. However, if the postmaster has died, we give up and return + * BGWH_POSTMASTER_DIED, since it that case we know that startup will not + * take place. + */ +BgwHandleStatus +WaitForBackgroundWorkerStartup(BackgroundWorkerHandle *handle, pid_t *pidp) +{ + BgwHandleStatus status; + pid_t pid; + int rc; + bool save_set_latch_on_sigusr1; + + save_set_latch_on_sigusr1 = set_latch_on_sigusr1; + set_latch_on_sigusr1 = true; + + PG_TRY(); + { + for (;;) + { + CHECK_FOR_INTERRUPTS(); + + status = GetBackgroundWorkerPid(handle, &pid); + if (status != BGWH_NOT_YET_STARTED) + break; + + rc = WaitLatch(&MyProc->procLatch, + WL_LATCH_SET | WL_POSTMASTER_DEATH, 0); + + if (rc & WL_POSTMASTER_DEATH) + { + status = BGWH_POSTMASTER_DIED; + break; + } + + ResetLatch(&MyProc->procLatch); + } + } + PG_CATCH(); + { + set_latch_on_sigusr1 = save_set_latch_on_sigusr1; + PG_RE_THROW(); + } + PG_END_TRY(); + + set_latch_on_sigusr1 = save_set_latch_on_sigusr1; + *pidp = pid; + return status; +} diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 13f4147d77..56432828d7 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -170,6 +170,7 @@ typedef struct bkend */ int bkend_type; bool dead_end; /* is it going to send an error and quit? */ + bool bgworker_notify; /* gets bgworker start/stop notifications */ dlist_node elem; /* list link in BackendList */ } Backend; @@ -2877,11 +2878,20 @@ CleanupBackgroundWorker(int pid, #ifdef EXEC_BACKEND ShmemBackendArrayRemove(rw->rw_backend); #endif + /* + * It's possible that this background worker started some OTHER + * background worker and asked to be notified when that worker + * started or stopped. If so, cancel any notifications destined + * for the now-dead backend. + */ + if (rw->rw_backend->bgworker_notify) + BackgroundWorkerStopNotifications(rw->rw_pid); free(rw->rw_backend); rw->rw_backend = NULL; } rw->rw_pid = 0; rw->rw_child_slot = 0; + ReportBackgroundWorkerPID(rw); /* report child death */ LogChildExit(LOG, namebuf, pid, exitstatus); @@ -2955,6 +2965,18 @@ CleanupBackend(int pid, ShmemBackendArrayRemove(bp); #endif } + if (bp->bgworker_notify) + { + /* + * This backend may have been slated to receive SIGUSR1 + * when some background worker started or stopped. Cancel + * those notifications, as we don't want to signal PIDs that + * are not PostgreSQL backends. This gets skipped in the + * (probably very common) case where the backend has never + * requested any such notifications. + */ + BackgroundWorkerStopNotifications(bp->pid); + } dlist_delete(iter.cur); free(bp); break; @@ -3018,6 +3040,7 @@ HandleChildCrash(int pid, int exitstatus, const char *procname) rw->rw_pid = 0; rw->rw_child_slot = 0; /* don't reset crashed_at */ + /* don't report child stop, either */ /* Keep looping so we can signal remaining workers */ } else @@ -3712,6 +3735,9 @@ BackendStartup(Port *port) else bn->child_slot = 0; + /* Hasn't asked to be notified about any bgworkers yet */ + bn->bgworker_notify = false; + #ifdef EXEC_BACKEND pid = backend_forkexec(port); #else /* !EXEC_BACKEND */ @@ -5122,6 +5148,7 @@ StartAutovacuumWorker(void) /* Autovac workers are not dead_end and need a child slot */ bn->dead_end = false; bn->child_slot = MyPMChildSlot = AssignPostmasterChildSlot(); + bn->bgworker_notify = false; bn->pid = StartAutoVacWorker(); if (bn->pid > 0) @@ -5318,6 +5345,7 @@ do_start_bgworker(RegisteredBgWorker *rw) rw->rw_pid = worker_pid; if (rw->rw_backend) rw->rw_backend->pid = rw->rw_pid; + ReportBackgroundWorkerPID(rw); } } @@ -5400,6 +5428,7 @@ assign_backendlist_entry(RegisteredBgWorker *rw) bn->child_slot = MyPMChildSlot = AssignPostmasterChildSlot(); bn->bkend_type = BACKEND_TYPE_BGWORKER; bn->dead_end = false; + bn->bgworker_notify = false; rw->rw_backend = bn; rw->rw_child_slot = bn->child_slot; @@ -5510,6 +5539,29 @@ maybe_start_bgworker(void) StartWorkerNeeded = false; } +/* + * When a backend asks to be notified about worker state changes, we + * set a flag in its backend entry. The background worker machinery needs + * to know when such backends exit. + */ +bool +PostmasterMarkPIDForWorkerNotify(int pid) +{ + dlist_iter iter; + Backend *bp; + + dlist_foreach(iter, &BackendList) + { + bp = dlist_container(Backend, elem, iter.cur); + if (bp->pid == pid) + { + bp->bgworker_notify = true; + return true; + } + } + return false; +} + #ifdef EXEC_BACKEND /* diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c index a6f77c105c..c4b5d0196b 100644 --- a/src/backend/storage/ipc/procsignal.c +++ b/src/backend/storage/ipc/procsignal.c @@ -21,6 +21,7 @@ #include "miscadmin.h" #include "storage/latch.h" #include "storage/ipc.h" +#include "storage/proc.h" #include "storage/shmem.h" #include "storage/sinval.h" #include "tcop/tcopprot.h" @@ -57,6 +58,14 @@ typedef struct */ #define NumProcSignalSlots (MaxBackends + NUM_AUXPROCTYPES) +/* + * If this flag is set, the process latch will be set whenever SIGUSR1 + * is received. This is useful when waiting for a signal from the postmaster. + * Spurious wakeups must be expected. Make sure that the flag is cleared + * in the error path. + */ +bool set_latch_on_sigusr1; + static ProcSignalSlot *ProcSignalSlots = NULL; static volatile ProcSignalSlot *MyProcSignalSlot = NULL; @@ -276,6 +285,9 @@ procsignal_sigusr1_handler(SIGNAL_ARGS) if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN)) RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN); + if (set_latch_on_sigusr1) + SetLatch(&MyProc->procLatch); + latch_sigusr1_handler(); errno = save_errno; diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index edced29f51..0aa540a08e 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -28,6 +28,8 @@ #define PG_BACKEND_VERSIONSTR "postgres (PostgreSQL) " PG_VERSION "\n" +#define InvalidPid (-1) + /***************************************************************************** * System interrupt and critical section handling diff --git a/src/include/postmaster/bgworker.h b/src/include/postmaster/bgworker.h index 0bb897b8f3..8bbbeb492c 100644 --- a/src/include/postmaster/bgworker.h +++ b/src/include/postmaster/bgworker.h @@ -80,13 +80,32 @@ typedef struct BackgroundWorker char bgw_library_name[BGW_MAXLEN]; /* only if bgw_main is NULL */ char bgw_function_name[BGW_MAXLEN]; /* only if bgw_main is NULL */ Datum bgw_main_arg; + pid_t bgw_notify_pid; /* SIGUSR1 this backend on start/stop */ } BackgroundWorker; +typedef enum BgwHandleStatus +{ + BGWH_STARTED, /* worker is running */ + BGWH_NOT_YET_STARTED, /* worker hasn't been started yet */ + BGWH_STOPPED, /* worker has exited */ + BGWH_POSTMASTER_DIED /* postmaster died; worker status unclear */ +} BgwHandleStatus; + +struct BackgroundWorkerHandle; +typedef struct BackgroundWorkerHandle BackgroundWorkerHandle; + /* Register a new bgworker during shared_preload_libraries */ extern void RegisterBackgroundWorker(BackgroundWorker *worker); /* Register a new bgworker from a regular backend */ -extern bool RegisterDynamicBackgroundWorker(BackgroundWorker *worker); +extern bool RegisterDynamicBackgroundWorker(BackgroundWorker *worker, + BackgroundWorkerHandle **handle); + +/* Query the status of a bgworker */ +extern BgwHandleStatus GetBackgroundWorkerPid(BackgroundWorkerHandle *handle, + pid_t *pidp); +extern BgwHandleStatus WaitForBackgroundWorkerStartup(BackgroundWorkerHandle * + handle, pid_t *pid); /* This is valid in a running worker */ extern BackgroundWorker *MyBgworkerEntry; diff --git a/src/include/postmaster/bgworker_internals.h b/src/include/postmaster/bgworker_internals.h index 3b53027fd4..6d5ee20dc3 100644 --- a/src/include/postmaster/bgworker_internals.h +++ b/src/include/postmaster/bgworker_internals.h @@ -40,6 +40,8 @@ extern Size BackgroundWorkerShmemSize(void); extern void BackgroundWorkerShmemInit(void); extern void BackgroundWorkerStateChange(void); extern void ForgetBackgroundWorker(slist_mutable_iter *cur); +extern void ReportBackgroundWorkerPID(RegisteredBgWorker *); +extern void BackgroundWorkerStopNotifications(pid_t pid); /* Function to start a background worker, called from postmaster.c */ extern void StartBackgroundWorker(void); diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h index c090595a45..5dc6dc5a5f 100644 --- a/src/include/postmaster/postmaster.h +++ b/src/include/postmaster/postmaster.h @@ -52,6 +52,7 @@ extern void ClosePostmasterPorts(bool am_syslogger); extern int MaxLivePostmasterChildren(void); extern int GetNumShmemAttachedBgworkers(void); +extern bool PostmasterMarkPIDForWorkerNotify(int); #ifdef EXEC_BACKEND extern pid_t postmaster_forkexec(int argc, char *argv[]); diff --git a/src/include/storage/procsignal.h b/src/include/storage/procsignal.h index 0f4b0cf812..73cec8fcae 100644 --- a/src/include/storage/procsignal.h +++ b/src/include/storage/procsignal.h @@ -54,5 +54,6 @@ extern int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId); extern void procsignal_sigusr1_handler(SIGNAL_ARGS); +extern bool set_latch_on_sigusr1; #endif /* PROCSIGNAL_H */