aboutsummaryrefslogtreecommitdiff
path: root/src/backend/postmaster/bgworker.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/postmaster/bgworker.c')
-rw-r--r--src/backend/postmaster/bgworker.c81
1 files changed, 53 insertions, 28 deletions
diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index 10e0f88b0de..0823317b780 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -15,12 +15,14 @@
#include <unistd.h>
#include "libpq/pqsignal.h"
+#include "access/parallel.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "port/atomics.h"
#include "postmaster/bgworker_internals.h"
#include "postmaster/postmaster.h"
#include "replication/logicallauncher.h"
+#include "replication/logicalworker.h"
#include "storage/dsm.h"
#include "storage/ipc.h"
#include "storage/latch.h"
@@ -109,14 +111,26 @@ struct BackgroundWorkerHandle
static BackgroundWorkerArray *BackgroundWorkerData;
/*
- * List of workers that are allowed to be started outside of
- * shared_preload_libraries.
+ * List of internal background workers. These are used for mapping the
+ * function name to actual function when building with EXEC_BACKEND and also
+ * to allow these to be loaded outside of shared_preload_libraries.
*/
-static const bgworker_main_type InternalBGWorkers[] = {
- ApplyLauncherMain,
- NULL
+typedef struct InternalBGWorkerMain
+{
+ char *bgw_function_name;
+ bgworker_main_type bgw_main;
+} InternalBGWorkerMain;
+
+static const InternalBGWorkerMain InternalBGWorkers[] = {
+ {"ParallelWorkerMain", ParallelWorkerMain},
+ {"ApplyLauncherMain", ApplyLauncherMain},
+ {"ApplyWorkerMain", ApplyWorkerMain},
+ /* Dummy entry marking end of the array. */
+ {NULL, NULL}
};
+static bgworker_main_type GetInternalBgWorkerMain(BackgroundWorker *worker);
+
/*
* Calculate shared memory needed.
*/
@@ -341,7 +355,6 @@ BackgroundWorkerStateChange(void)
rw->rw_worker.bgw_flags = slot->worker.bgw_flags;
rw->rw_worker.bgw_start_time = slot->worker.bgw_start_time;
rw->rw_worker.bgw_restart_time = slot->worker.bgw_restart_time;
- rw->rw_worker.bgw_main = slot->worker.bgw_main;
rw->rw_worker.bgw_main_arg = slot->worker.bgw_main_arg;
memcpy(rw->rw_worker.bgw_extra, slot->worker.bgw_extra, BGW_EXTRALEN);
@@ -763,17 +776,14 @@ StartBackgroundWorker(void)
}
/*
- * If bgw_main is set, we use that value as the initial entrypoint.
- * However, if the library containing the entrypoint wasn't loaded at
- * postmaster startup time, passing it as a direct function pointer is not
- * possible. To work around that, we allow callers for whom a function
- * pointer is not available to pass a library name (which will be loaded,
- * if necessary) and a function name (which will be looked up in the named
- * library).
+ * For internal workers set the entry point to known function address.
+ * Otherwise use the entry point specified by library name (which will
+ * be loaded, if necessary) and a function name (which will be looked up
+ * in the named library).
*/
- if (worker->bgw_main != NULL)
- entrypt = worker->bgw_main;
- else
+ entrypt = GetInternalBgWorkerMain(worker);
+
+ if (entrypt == NULL)
entrypt = (bgworker_main_type)
load_external_function(worker->bgw_library_name,
worker->bgw_function_name,
@@ -806,23 +816,13 @@ RegisterBackgroundWorker(BackgroundWorker *worker)
{
RegisteredBgWorker *rw;
static int numworkers = 0;
- bool internal = false;
- int i;
if (!IsUnderPostmaster)
ereport(DEBUG1,
(errmsg("registering background worker \"%s\"", worker->bgw_name)));
- for (i = 0; InternalBGWorkers[i]; i++)
- {
- if (worker->bgw_main == InternalBGWorkers[i])
- {
- internal = true;
- break;
- }
- }
-
- if (!process_shared_preload_libraries_in_progress && !internal)
+ if (!process_shared_preload_libraries_in_progress &&
+ GetInternalBgWorkerMain(worker) == NULL)
{
if (!IsUnderPostmaster)
ereport(LOG,
@@ -1152,3 +1152,28 @@ TerminateBackgroundWorker(BackgroundWorkerHandle *handle)
if (signal_postmaster)
SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE);
}
+
+/*
+ * Search the known internal worker array and return its main function
+ * pointer if found.
+ *
+ * Returns NULL if not known internal worker.
+ */
+static bgworker_main_type
+GetInternalBgWorkerMain(BackgroundWorker *worker)
+{
+ int i;
+
+ /* Internal workers always have to use postgres as library name. */
+ if (strncmp(worker->bgw_library_name, "postgres", BGW_MAXLEN) != 0)
+ return NULL;
+
+ for (i = 0; InternalBGWorkers[i].bgw_function_name; i++)
+ {
+ if (strncmp(InternalBGWorkers[i].bgw_function_name,
+ worker->bgw_function_name, BGW_MAXLEN) == 0)
+ return InternalBGWorkers[i].bgw_main;
+ }
+
+ return NULL;
+}