agora inbox for [email protected]
help / color / mirror / Atom feedFrom: Mike Palmiotto <[email protected]>
Subject: [PATCH v2 08/12] Add BgWorkerType to subprocess struct
Date: Wed, 11 Mar 2020 03:32:41 +0000
Export some of the backend-specific code and move the some bgworker
startup code out to src/backend/postmaster/bgworker.c.
---
src/backend/postmaster/bgworker.c | 165 ++++++++++-
src/backend/postmaster/postmaster.c | 294 +++-----------------
src/backend/postmaster/subprocess.c | 12 +
src/backend/utils/init/globals.c | 1 +
src/include/miscadmin.h | 1 +
src/include/postmaster/bgworker_internals.h | 8 +-
src/include/postmaster/postmaster.h | 53 ++++
src/include/postmaster/subprocess.h | 1 +
8 files changed, 268 insertions(+), 267 deletions(-)
diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index 6c684b5e12..6f62cd4889 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -33,8 +33,10 @@
#include "storage/shmem.h"
#include "tcop/tcopprot.h"
#include "utils/ascii.h"
+#include "utils/memutils.h"
#include "utils/ps_status.h"
#include "utils/timeout.h"
+#include "utils/timestamp.h"
/*
* The postmaster's list of registered background workers, in private memory.
@@ -133,7 +135,55 @@ static const struct
/* Private functions. */
static bgworker_main_type LookupBackgroundWorkerFunction(const char *libraryname, const char *funcname);
+static bool assign_backendlist_entry(RegisteredBgWorker *rw);
+/*
+ * Allocate the Backend struct for a connected background worker, but don't
+ * add it to the list of backends just yet.
+ *
+ * On failure, return false without changing any worker state.
+ *
+ * Some info from the Backend is copied into the passed rw.
+ */
+static bool
+assign_backendlist_entry(RegisteredBgWorker *rw)
+{
+ Backend *bn;
+
+ /*
+ * Compute the cancel key that will be assigned to this session. We
+ * probably don't need cancel keys for background workers, but we'd better
+ * have something random in the field to prevent unfriendly people from
+ * sending cancels to them.
+ */
+ if (!RandomCancelKey(&MyCancelKey))
+ {
+ ereport(LOG,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("could not generate random cancel key")));
+ return false;
+ }
+
+ bn = malloc(sizeof(Backend));
+ if (bn == NULL)
+ {
+ ereport(LOG,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
+ return false;
+ }
+
+ bn->cancel_key = MyCancelKey;
+ 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;
+
+ return true;
+}
/*
* Calculate shared memory needed.
@@ -670,6 +720,55 @@ bgworker_sigusr1_handler(SIGNAL_ARGS)
errno = save_errno;
}
+/*
+ * BackgroundWorkerPrep
+ *
+ * Postmaster subroutine to prepare a bgworker subprocess.
+ *
+ * Returns 0 on success or -1 on failure.
+ *
+ * Note: if fail, we will be called again from the postmaster main loop.
+ */
+int
+BackgroundWorkerPrep(int argc, char *argv[])
+{
+ RegisteredBgWorker *rw = MyRegisteredBgWorker;
+#ifdef EXEC_BACKEND
+ char forkav[MAXPGPATH];
+#endif
+
+ Assert(MyRegisteredBgWorker);
+ Assert(rw->rw_pid == 0);
+
+ /*
+ * Allocate and assign the Backend element. Note we must do this before
+ * forking, so that we can handle out of memory properly.
+ *
+ * Treat failure as though the worker had crashed. That way, the
+ * postmaster will wait a bit before attempting to start it again; if it
+ * tried again right away, most likely it'd find itself repeating the
+ * out-of-memory or fork failure condition.
+ */
+ if (!assign_backendlist_entry(rw))
+ {
+ rw->rw_crashed_at = GetCurrentTimestamp();
+ return -1;
+ }
+
+ ereport(DEBUG1,
+ (errmsg("starting background worker process \"%s\"",
+ rw->rw_worker.bgw_name)));
+
+#ifdef EXEC_BACKEND
+ /* Rewrite bgworker fork parameter with shmem_slot */
+ snprintf(forkav, MAXPGPATH, "%s=%d", argv[1], rw->rw_shmem_slot);
+ argv[1] = forkav;
+#endif
+
+ return 0;
+}
+
+
/*
* Start a new background worker
*
@@ -677,12 +776,28 @@ bgworker_sigusr1_handler(SIGNAL_ARGS)
* postmaster.
*/
void
-StartBackgroundWorker(void)
+BackgroundWorkerMain(pg_attribute_unused() int argc, pg_attribute_unused() char *argv[])
{
sigjmp_buf local_sigjmp_buf;
- BackgroundWorker *worker = MyBgworkerEntry;
+ BackgroundWorker *worker;
bgworker_main_type entrypt;
+#ifndef EXEC_BACKEND
+ /*
+ * Before blowing away PostmasterContext, save this bgworker's
+ * data where it can find it.
+ */
+ MyBgworkerEntry = (BackgroundWorker *)
+ MemoryContextAlloc(TopMemoryContext, sizeof(BackgroundWorker));
+ memcpy(MyBgworkerEntry, &(MyRegisteredBgWorker->rw_worker), sizeof(BackgroundWorker));
+
+ /* Now we can release postmaster's working memory context */
+ MemoryContextSwitchTo(TopMemoryContext);
+ MemoryContextDelete(PostmasterContext);
+ PostmasterContext = NULL;
+#endif
+
+ worker = MyBgworkerEntry;
if (worker == NULL)
elog(FATAL, "unable to find bgworker entry");
@@ -816,6 +931,52 @@ StartBackgroundWorker(void)
proc_exit(0);
}
+/*
+ * BackgroundWorkerForkFailure
+ *
+ * Handle bgworker fork failure gracefully.
+ */
+bool
+BackgroundWorkerForkFailure(int fork_errno)
+{
+ RegisteredBgWorker *rw = MyRegisteredBgWorker;
+
+ errno = fork_errno;
+
+ /* in postmaster, fork failed ... */
+ ereport(LOG,
+ (errmsg("could not fork worker process: %m")));
+
+ /* undo what assign_backendlist_entry did */
+ ReleasePostmasterChildSlot(rw->rw_child_slot);
+ rw->rw_child_slot = 0;
+ free(rw->rw_backend);
+ rw->rw_backend = NULL;
+ /* mark entry as crashed, so we'll try again later */
+ rw->rw_crashed_at = GetCurrentTimestamp();
+
+ /* Don't panic. */
+ return false;
+}
+
+/*
+ * BackgroundWorkerPostmasterMain
+ */
+void
+BackgroundWorkerPostmasterMain(pg_attribute_unused() int argc, pg_attribute_unused() char *argv[])
+{
+ RegisteredBgWorker *rw = MyRegisteredBgWorker;
+
+ rw->rw_pid = MyChildProcPid;
+ rw->rw_backend->pid = rw->rw_pid;
+ ReportBackgroundWorkerPID(rw);
+ /* add new worker to lists of backends */
+ dlist_push_head(&BackendList, &(rw->rw_backend->elem));
+#ifdef EXEC_BACKEND
+ ShmemBackendArrayAdd(rw->rw_backend);
+#endif
+}
+
/*
* Register a new static background worker.
*
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index f724727b1e..8343a81923 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -137,60 +137,14 @@
#include "storage/spin.h"
#endif
-
-/*
- * Possible types of a backend. Beyond being the possible bkend_type values in
- * struct bkend, these are OR-able request flag bits for SignalSomeChildren()
- * and CountChildren().
- */
-#define BACKEND_TYPE_NORMAL 0x0001 /* normal backend */
-#define BACKEND_TYPE_AUTOVAC 0x0002 /* autovacuum worker process */
-#define BACKEND_TYPE_WALSND 0x0004 /* walsender process */
-#define BACKEND_TYPE_BGWORKER 0x0008 /* bgworker process */
-#define BACKEND_TYPE_ALL 0x000F /* OR of all the above */
-
-#define BACKEND_TYPE_WORKER (BACKEND_TYPE_AUTOVAC | BACKEND_TYPE_BGWORKER)
-
-/*
- * List of active backends (or child processes anyway; we don't actually
- * know whether a given child has become a backend or is still in the
- * authorization phase). This is used mainly to keep track of how many
- * children we have and send them appropriate signals when necessary.
- *
- * "Special" children such as the startup, bgwriter and autovacuum launcher
- * tasks are not in this list. Autovacuum worker and walsender are in it.
- * Also, "dead_end" children are in it: these are children launched just for
- * the purpose of sending a friendly rejection message to a would-be client.
- * We must track them because they are attached to shared memory, but we know
- * they will never become live backends. dead_end children are not assigned a
- * PMChildSlot.
- *
- * Background workers are in this list, too.
- */
-typedef struct bkend
-{
- pid_t pid; /* process id of backend */
- int32 cancel_key; /* cancel key for cancels for this backend */
- int child_slot; /* PMChildSlot for this backend, if any */
-
- /*
- * Flavor of backend or auxiliary process. Note that BACKEND_TYPE_WALSND
- * backends initially announce themselves as BACKEND_TYPE_NORMAL, so if
- * bkend_type is normal, you should check for a recent transition.
- */
- 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;
-
-static dlist_head BackendList = DLIST_STATIC_INIT(BackendList);
+dlist_head BackendList = DLIST_STATIC_INIT(BackendList);
#ifdef EXEC_BACKEND
static Backend *ShmemBackendArray;
#endif
BackgroundWorker *MyBgworkerEntry = NULL;
+RegisteredBgWorker *MyRegisteredBgWorker = NULL;
/* Struct containing postmaster subprocess control info */
SubprocessType MySubprocessType;
@@ -412,7 +366,6 @@ static void processCancelRequest(Port *port, void *pkt);
static int initMasks(fd_set *rmask);
static void report_fork_failure_to_client(Port *port, int errnum);
static CAC_state canAcceptConnections(int backend_type);
-static bool RandomCancelKey(int32 *cancel_key);
static void signal_child(pid_t pid, int signal);
static bool SignalSomeChildren(int signal, int targets);
static void TerminateChildren(int signal);
@@ -420,7 +373,6 @@ static void TerminateChildren(int signal);
#define SignalChildren(sig) SignalSomeChildren(sig, BACKEND_TYPE_ALL)
static int CountChildren(int target);
-static bool assign_backendlist_entry(RegisteredBgWorker *rw);
static void maybe_start_bgworkers(void);
static bool CreateOptsFile(int argc, char *argv[], char *fullprogname);
static pid_t StartSubprocess(SubprocessType type);
@@ -539,10 +491,10 @@ static bool save_backend_variables(BackendParameters *param, Port *port,
HANDLE childProcess, pid_t childPid);
#endif
-static void ShmemBackendArrayAdd(Backend *bn);
static void ShmemBackendArrayRemove(Backend *bn);
#endif /* EXEC_BACKEND */
+#define BGWORKER_LEN 15
/* Macros to check exit status of a child process */
#define EXIT_STATUS_0(st) ((st) == 0)
@@ -4878,6 +4830,7 @@ void
SubPostmasterMain(int argc, char *argv[])
{
Port port;
+ int shmem_slot;
/* In EXEC_BACKEND case we will not have inherited these settings */
IsPostmasterEnvironment = true;
@@ -5041,59 +4994,48 @@ SubPostmasterMain(int argc, char *argv[])
/* And run the backend */
BackendRun(&port); /* does not return */
}
- if (strncmp(argv[1], "--forkbgworker=", 15) == 0)
- {
- int shmem_slot;
-
- /* do this as early as possible; in particular, before InitProcess() */
- IsBackgroundWorker = true;
+ if (MySubprocess->needs_aux_proc)
+ {
/* Restore basic shared memory pointers */
InitShmemAccess(UsedShmemSegAddr);
/* Need a PGPROC to run CreateSharedMemoryAndSemaphores */
- InitProcess();
+ InitAuxiliaryProcess();
/* Attach process to shared data structures */
CreateSharedMemoryAndSemaphores();
- /* Fetch MyBgworkerEntry from shared memory */
- shmem_slot = atoi(argv[1] + 15);
- MyBgworkerEntry = BackgroundWorkerEntry(shmem_slot);
+ AuxiliaryProcessMain(argc - 2, argv + 2); /* does not return */
+ }
- StartBackgroundWorker();
+ if (MySubprocessType == BgWorkerType)
+ {
+ /* do this as early as possible; in particular, before InitProcess() */
+ IsBackgroundWorker = true;
}
- if (MySubprocess->needs_aux_proc)
+ if (MySubprocess->needs_shmem)
{
/* Restore basic shared memory pointers */
InitShmemAccess(UsedShmemSegAddr);
/* Need a PGPROC to run CreateSharedMemoryAndSemaphores */
- InitAuxiliaryProcess();
+ InitProcess();
/* Attach process to shared data structures */
CreateSharedMemoryAndSemaphores();
-
- AuxiliaryProcessMain(argc - 2, argv + 2); /* does not return */
}
- else
- {
- if (MySubprocess->needs_shmem)
- {
- /* Restore basic shared memory pointers */
- InitShmemAccess(UsedShmemSegAddr);
-
- /* Need a PGPROC to run CreateSharedMemoryAndSemaphores */
- InitProcess();
- /* Attach process to shared data structures */
- CreateSharedMemoryAndSemaphores();
- }
-
- MySubprocess->entrypoint(argc - 2, argv + 2);
+ if (MySubprocessType == BgWorkerType)
+ {
+ /* Fetch MyBgworkerEntry from shared memory */
+ shmem_slot = atoi(argv[1] + 15);
+ MyBgworkerEntry = BackgroundWorkerEntry(shmem_slot);
}
+ MySubprocess->entrypoint(argc - 2, argv + 2);
+
abort(); /* shouldn't get here */
}
#endif /* EXEC_BACKEND */
@@ -5356,7 +5298,7 @@ StartupPacketTimeoutHandler(void)
/*
* Generate a random cancel key.
*/
-static bool
+bool
RandomCancelKey(int32 *cancel_key)
{
return pg_strong_random(cancel_key, sizeof(int32));
@@ -5454,15 +5396,17 @@ StartSubprocess(SubprocessType type)
#ifdef EXEC_BACKEND
pid = postmaster_forkexec(argc, argv);
+ MyChildProcPid = pid;
#else /* !EXEC_BACKEND */
pid = fork_process();
+ MyChildProcPid = pid;
if (pid == 0) /* child */
{
InitPostmasterChild();
/* Close the postmaster's sockets */
- ClosePostmasterPorts(false);
+ ClosePostmasterPorts(MySubprocessType == SysLoggerType);
/*
* Release postmaster's working memory context if the subprocess doesn't
@@ -5512,6 +5456,8 @@ StartSubprocess(SubprocessType type)
{
if (MySubprocess->fork_failure(save_errno))
ExitPostmaster(1);
+ else
+ return -1;
}
return 0;
@@ -5754,124 +5700,6 @@ BackgroundWorkerUnblockSignals(void)
PG_SETMASK(&UnBlockSig);
}
-#ifdef EXEC_BACKEND
-static pid_t
-bgworker_forkexec(int shmem_slot)
-{
- char *av[10];
- int ac = 0;
- char forkav[MAXPGPATH];
-
- snprintf(forkav, MAXPGPATH, "--forkbgworker=%d", shmem_slot);
-
- av[ac++] = "postgres";
- av[ac++] = forkav;
- av[ac++] = NULL; /* filled in by postmaster_forkexec */
- av[ac] = NULL;
-
- Assert(ac < lengthof(av));
-
- return postmaster_forkexec(ac, av);
-}
-#endif
-
-/*
- * Start a new bgworker.
- * Starting time conditions must have been checked already.
- *
- * Returns true on success, false on failure.
- * In either case, update the RegisteredBgWorker's state appropriately.
- *
- * This code is heavily based on autovacuum.c, q.v.
- */
-static bool
-do_start_bgworker(RegisteredBgWorker *rw)
-{
- pid_t worker_pid;
-
- Assert(rw->rw_pid == 0);
-
- /*
- * Allocate and assign the Backend element. Note we must do this before
- * forking, so that we can handle failures (out of memory or child-process
- * slots) cleanly.
- *
- * Treat failure as though the worker had crashed. That way, the
- * postmaster will wait a bit before attempting to start it again; if we
- * tried again right away, most likely we'd find ourselves hitting the
- * same resource-exhaustion condition.
- */
- if (!assign_backendlist_entry(rw))
- {
- rw->rw_crashed_at = GetCurrentTimestamp();
- return false;
- }
-
- ereport(DEBUG1,
- (errmsg("starting background worker process \"%s\"",
- rw->rw_worker.bgw_name)));
-
-#ifdef EXEC_BACKEND
- switch ((worker_pid = bgworker_forkexec(rw->rw_shmem_slot)))
-#else
- switch ((worker_pid = fork_process()))
-#endif
- {
- case -1:
- /* in postmaster, fork failed ... */
- ereport(LOG,
- (errmsg("could not fork worker process: %m")));
- /* undo what assign_backendlist_entry did */
- ReleasePostmasterChildSlot(rw->rw_child_slot);
- rw->rw_child_slot = 0;
- free(rw->rw_backend);
- rw->rw_backend = NULL;
- /* mark entry as crashed, so we'll try again later */
- rw->rw_crashed_at = GetCurrentTimestamp();
- break;
-
-#ifndef EXEC_BACKEND
- case 0:
- /* in postmaster child ... */
- InitPostmasterChild();
-
- /* Close the postmaster's sockets */
- ClosePostmasterPorts(false);
-
- /*
- * Before blowing away PostmasterContext, save this bgworker's
- * data where it can find it.
- */
- MyBgworkerEntry = (BackgroundWorker *)
- MemoryContextAlloc(TopMemoryContext, sizeof(BackgroundWorker));
- memcpy(MyBgworkerEntry, &rw->rw_worker, sizeof(BackgroundWorker));
-
- /* Release postmaster's working memory context */
- MemoryContextSwitchTo(TopMemoryContext);
- MemoryContextDelete(PostmasterContext);
- PostmasterContext = NULL;
-
- StartBackgroundWorker();
-
- exit(1); /* should not get here */
- break;
-#endif
- default:
- /* in postmaster, fork successful ... */
- rw->rw_pid = worker_pid;
- rw->rw_backend->pid = rw->rw_pid;
- ReportBackgroundWorkerPID(rw);
- /* add new worker to lists of backends */
- dlist_push_head(&BackendList, &rw->rw_backend->elem);
-#ifdef EXEC_BACKEND
- ShmemBackendArrayAdd(rw->rw_backend);
-#endif
- return true;
- }
-
- return false;
-}
-
/*
* Does the current postmaster state require starting a worker with the
* specified start_time?
@@ -5912,67 +5740,6 @@ bgworker_should_start_now(BgWorkerStartTime start_time)
return false;
}
-/*
- * Allocate the Backend struct for a connected background worker, but don't
- * add it to the list of backends just yet.
- *
- * On failure, return false without changing any worker state.
- *
- * Some info from the Backend is copied into the passed rw.
- */
-static bool
-assign_backendlist_entry(RegisteredBgWorker *rw)
-{
- Backend *bn;
-
- /*
- * Check that database state allows another connection. Currently the
- * only possible failure is CAC_TOOMANY, so we just log an error message
- * based on that rather than checking the error code precisely.
- */
- if (canAcceptConnections(BACKEND_TYPE_BGWORKER) != CAC_OK)
- {
- ereport(LOG,
- (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
- errmsg("no slot available for new worker process")));
- return false;
- }
-
- /*
- * Compute the cancel key that will be assigned to this session. We
- * probably don't need cancel keys for background workers, but we'd better
- * have something random in the field to prevent unfriendly people from
- * sending cancels to them.
- */
- if (!RandomCancelKey(&MyCancelKey))
- {
- ereport(LOG,
- (errcode(ERRCODE_INTERNAL_ERROR),
- errmsg("could not generate random cancel key")));
- return false;
- }
-
- bn = malloc(sizeof(Backend));
- if (bn == NULL)
- {
- ereport(LOG,
- (errcode(ERRCODE_OUT_OF_MEMORY),
- errmsg("out of memory")));
- return false;
- }
-
- bn->cancel_key = MyCancelKey;
- 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;
-
- return true;
-}
-
/*
* If the time is right, start background worker(s).
*
@@ -6077,7 +5844,8 @@ maybe_start_bgworkers(void)
* crashed, but there's no need because the next run of this
* function will do that.
*/
- if (!do_start_bgworker(rw))
+ MyRegisteredBgWorker = rw;
+ if (StartSubprocess(BgWorkerType) <= 0)
{
StartWorkerNeeded = true;
return;
@@ -6488,7 +6256,7 @@ ShmemBackendArrayAllocation(void)
memset(ShmemBackendArray, 0, size);
}
-static void
+void
ShmemBackendArrayAdd(Backend *bn)
{
/* The array slot corresponding to my PMChildSlot should be free */
diff --git a/src/backend/postmaster/subprocess.c b/src/backend/postmaster/subprocess.c
index f9d07de4ae..d4df791aeb 100644
--- a/src/backend/postmaster/subprocess.c
+++ b/src/backend/postmaster/subprocess.c
@@ -14,6 +14,7 @@
#include "bootstrap/bootstrap.h"
#include "pgstat.h"
#include "postmaster/autovacuum.h"
+#include "postmaster/bgworker_internals.h"
#include "postmaster/bgwriter.h"
#include "postmaster/pgarch.h"
#include "postmaster/postmaster.h"
@@ -158,6 +159,17 @@ static PgSubprocess process_types[] = {
.entrypoint = SysLoggerMain,
.fork_failure = NULL,
.postmaster_main = SysLoggerPostmasterMain
+ },
+ {
+ .name = "bgworker",
+ .desc = "background worker",
+ .needs_aux_proc = false,
+ .needs_shmem = true,
+ .keep_postmaster_memcontext = true,
+ .fork_prep = BackgroundWorkerPrep,
+ .entrypoint = BackgroundWorkerMain,
+ .fork_failure = BackgroundWorkerForkFailure,
+ .postmaster_main = BackgroundWorkerPostmasterMain
}
};
diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c
index eb19644419..b31ce82f75 100644
--- a/src/backend/utils/init/globals.c
+++ b/src/backend/utils/init/globals.c
@@ -38,6 +38,7 @@ volatile uint32 QueryCancelHoldoffCount = 0;
volatile uint32 CritSectionCount = 0;
int MyProcPid;
+int MyChildProcPid;
pg_time_t MyStartTime;
TimestampTz MyStartTimestamp;
struct Port *MyProcPort;
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 14fa127ab1..541ca5145d 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -163,6 +163,7 @@ extern PGDLLIMPORT int max_worker_processes;
extern PGDLLIMPORT int max_parallel_workers;
extern PGDLLIMPORT int MyProcPid;
+extern PGDLLIMPORT int MyChildProcPid;
extern PGDLLIMPORT pg_time_t MyStartTime;
extern PGDLLIMPORT TimestampTz MyStartTimestamp;
extern PGDLLIMPORT struct Port *MyProcPort;
diff --git a/src/include/postmaster/bgworker_internals.h b/src/include/postmaster/bgworker_internals.h
index f7e24664d5..874d5a203f 100644
--- a/src/include/postmaster/bgworker_internals.h
+++ b/src/include/postmaster/bgworker_internals.h
@@ -43,6 +43,7 @@ typedef struct RegisteredBgWorker
} RegisteredBgWorker;
extern slist_head BackgroundWorkerList;
+extern RegisteredBgWorker *MyRegisteredBgWorker;
extern Size BackgroundWorkerShmemSize(void);
extern void BackgroundWorkerShmemInit(void);
@@ -53,8 +54,11 @@ extern void ReportBackgroundWorkerExit(slist_mutable_iter *cur);
extern void BackgroundWorkerStopNotifications(pid_t pid);
extern void ResetBackgroundWorkerCrashTimes(void);
-/* Function to start a background worker, called from postmaster.c */
-extern void StartBackgroundWorker(void) pg_attribute_noreturn();
+/* BgWorkerType subprocess */
+extern int BackgroundWorkerPrep(int argc, char *argv[]);
+extern void BackgroundWorkerMain(int argc, char *argv[]);
+extern bool BackgroundWorkerForkFailure(int fork_errno);
+extern void BackgroundWorkerPostmasterMain(int argc, char *argv[]);
#ifdef EXEC_BACKEND
extern BackgroundWorker *BackgroundWorkerEntry(int slotno);
diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h
index babc87dfc9..b1411c1ed2 100644
--- a/src/include/postmaster/postmaster.h
+++ b/src/include/postmaster/postmaster.h
@@ -13,6 +13,41 @@
#ifndef _POSTMASTER_H
#define _POSTMASTER_H
+#include "lib/ilist.h"
+
+/*
+ * List of active backends (or child processes anyway; we don't actually
+ * know whether a given child has become a backend or is still in the
+ * authorization phase). This is used mainly to keep track of how many
+ * children we have and send them appropriate signals when necessary.
+ *
+ * "Special" children such as the startup, bgwriter and autovacuum launcher
+ * tasks are not in this list. Autovacuum worker and walsender are in it.
+ * Also, "dead_end" children are in it: these are children launched just for
+ * the purpose of sending a friendly rejection message to a would-be client.
+ * We must track them because they are attached to shared memory, but we know
+ * they will never become live backends. dead_end children are not assigned a
+ * PMChildSlot.
+ *
+ * Background workers are in this list, too.
+ */
+typedef struct bkend
+{
+ pid_t pid; /* process id of backend */
+ int32 cancel_key; /* cancel key for cancels for this backend */
+ int child_slot; /* PMChildSlot for this backend, if any */
+
+ /*
+ * Flavor of backend or auxiliary process. Note that BACKEND_TYPE_WALSND
+ * backends initially announce themselves as BACKEND_TYPE_NORMAL, so if
+ * bkend_type is normal, you should check for a recent transition.
+ */
+ 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;
+
/* GUC options */
extern bool EnableSSL;
extern int ReservedBackends;
@@ -54,14 +89,19 @@ extern int MaxLivePostmasterChildren(void);
extern bool PostmasterMarkPIDForWorkerNotify(int);
+extern bool RandomCancelKey(int32 *cancel_key);
+
#ifdef EXEC_BACKEND
extern pid_t postmaster_forkexec(int argc, char *argv[]);
extern void SubPostmasterMain(int argc, char *argv[]) pg_attribute_noreturn();
extern Size ShmemBackendArraySize(void);
extern void ShmemBackendArrayAllocation(void);
+extern void ShmemBackendArrayAdd(Backend *bn);
#endif
+extern PGDLLIMPORT dlist_head BackendList;
+
/*
* Note: MAX_BACKENDS is limited to 2^18-1 because that's the width reserved
* for buffer references in buf_internals.h. This limitation could be lifted
@@ -74,4 +114,17 @@ extern void ShmemBackendArrayAllocation(void);
*/
#define MAX_BACKENDS 0x3FFFF
+/*
+ * Possible types of a backend. Beyond being the possible bkend_type values in
+ * struct bkend, these are OR-able request flag bits for SignalSomeChildren()
+ * and CountChildren().
+ */
+#define BACKEND_TYPE_NORMAL 0x0001 /* normal backend */
+#define BACKEND_TYPE_AUTOVAC 0x0002 /* autovacuum worker process */
+#define BACKEND_TYPE_WALSND 0x0004 /* walsender process */
+#define BACKEND_TYPE_BGWORKER 0x0008 /* bgworker process */
+#define BACKEND_TYPE_ALL 0x000F /* OR of all the above */
+
+#define BACKEND_TYPE_WORKER (BACKEND_TYPE_AUTOVAC | BACKEND_TYPE_BGWORKER)
+
#endif /* _POSTMASTER_H */
diff --git a/src/include/postmaster/subprocess.h b/src/include/postmaster/subprocess.h
index d0d98a5d69..706d60e4d6 100644
--- a/src/include/postmaster/subprocess.h
+++ b/src/include/postmaster/subprocess.h
@@ -28,6 +28,7 @@ typedef enum
PgstatCollectorType,
PgArchiverType,
SysLoggerType,
+ BgWorkerType,
NUMSUBPROCESSTYPES /* Must be last! */
} SubprocessType;
--
2.17.0
--FcSpk3Icpd/Pbul4
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
filename="v2-0009-Add-Backends-to-subprocess-struct.patch"
view thread (2+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected]
Subject: Re: [PATCH v2 08/12] Add BgWorkerType to subprocess struct
In-Reply-To: <no-message-id-198789@localhost>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox