|
15 | 15 | #include <unistd.h> |
16 | 16 |
|
17 | 17 | #include "libpq/pqsignal.h" |
| 18 | +#include "access/parallel.h" |
18 | 19 | #include "miscadmin.h" |
19 | 20 | #include "pgstat.h" |
20 | 21 | #include "port/atomics.h" |
21 | 22 | #include "postmaster/bgworker_internals.h" |
22 | 23 | #include "postmaster/postmaster.h" |
23 | 24 | #include "replication/logicallauncher.h" |
| 25 | +#include "replication/logicalworker.h" |
24 | 26 | #include "storage/dsm.h" |
25 | 27 | #include "storage/ipc.h" |
26 | 28 | #include "storage/latch.h" |
@@ -109,14 +111,26 @@ struct BackgroundWorkerHandle |
109 | 111 | static BackgroundWorkerArray *BackgroundWorkerData; |
110 | 112 |
|
111 | 113 | /* |
112 | | - * List of workers that are allowed to be started outside of |
113 | | - * shared_preload_libraries. |
| 114 | + * List of internal background workers. These are used for mapping the |
| 115 | + * function name to actual function when building with EXEC_BACKEND and also |
| 116 | + * to allow these to be loaded outside of shared_preload_libraries. |
114 | 117 | */ |
115 | | -static const bgworker_main_type InternalBGWorkers[] = { |
116 | | - ApplyLauncherMain, |
117 | | - NULL |
| 118 | +typedef struct InternalBGWorkerMain |
| 119 | +{ |
| 120 | + char *bgw_function_name; |
| 121 | + bgworker_main_type bgw_main; |
| 122 | +} InternalBGWorkerMain; |
| 123 | + |
| 124 | +static const InternalBGWorkerMain InternalBGWorkers[] = { |
| 125 | + {"ParallelWorkerMain", ParallelWorkerMain}, |
| 126 | + {"ApplyLauncherMain", ApplyLauncherMain}, |
| 127 | + {"ApplyWorkerMain", ApplyWorkerMain}, |
| 128 | + /* Dummy entry marking end of the array. */ |
| 129 | + {NULL, NULL} |
118 | 130 | }; |
119 | 131 |
|
| 132 | +static bgworker_main_type GetInternalBgWorkerMain(BackgroundWorker *worker); |
| 133 | + |
120 | 134 | /* |
121 | 135 | * Calculate shared memory needed. |
122 | 136 | */ |
@@ -341,7 +355,6 @@ BackgroundWorkerStateChange(void) |
341 | 355 | rw->rw_worker.bgw_flags = slot->worker.bgw_flags; |
342 | 356 | rw->rw_worker.bgw_start_time = slot->worker.bgw_start_time; |
343 | 357 | rw->rw_worker.bgw_restart_time = slot->worker.bgw_restart_time; |
344 | | - rw->rw_worker.bgw_main = slot->worker.bgw_main; |
345 | 358 | rw->rw_worker.bgw_main_arg = slot->worker.bgw_main_arg; |
346 | 359 | memcpy(rw->rw_worker.bgw_extra, slot->worker.bgw_extra, BGW_EXTRALEN); |
347 | 360 |
|
@@ -763,17 +776,14 @@ StartBackgroundWorker(void) |
763 | 776 | } |
764 | 777 |
|
765 | 778 | /* |
766 | | - * If bgw_main is set, we use that value as the initial entrypoint. |
767 | | - * However, if the library containing the entrypoint wasn't loaded at |
768 | | - * postmaster startup time, passing it as a direct function pointer is not |
769 | | - * possible. To work around that, we allow callers for whom a function |
770 | | - * pointer is not available to pass a library name (which will be loaded, |
771 | | - * if necessary) and a function name (which will be looked up in the named |
772 | | - * library). |
| 779 | + * For internal workers set the entry point to known function address. |
| 780 | + * Otherwise use the entry point specified by library name (which will |
| 781 | + * be loaded, if necessary) and a function name (which will be looked up |
| 782 | + * in the named library). |
773 | 783 | */ |
774 | | - if (worker->bgw_main != NULL) |
775 | | - entrypt = worker->bgw_main; |
776 | | - else |
| 784 | + entrypt = GetInternalBgWorkerMain(worker); |
| 785 | + |
| 786 | + if (entrypt == NULL) |
777 | 787 | entrypt = (bgworker_main_type) |
778 | 788 | load_external_function(worker->bgw_library_name, |
779 | 789 | worker->bgw_function_name, |
@@ -806,23 +816,13 @@ RegisterBackgroundWorker(BackgroundWorker *worker) |
806 | 816 | { |
807 | 817 | RegisteredBgWorker *rw; |
808 | 818 | static int numworkers = 0; |
809 | | - bool internal = false; |
810 | | - int i; |
811 | 819 |
|
812 | 820 | if (!IsUnderPostmaster) |
813 | 821 | ereport(DEBUG1, |
814 | 822 | (errmsg("registering background worker \"%s\"", worker->bgw_name))); |
815 | 823 |
|
816 | | - for (i = 0; InternalBGWorkers[i]; i++) |
817 | | - { |
818 | | - if (worker->bgw_main == InternalBGWorkers[i]) |
819 | | - { |
820 | | - internal = true; |
821 | | - break; |
822 | | - } |
823 | | - } |
824 | | - |
825 | | - if (!process_shared_preload_libraries_in_progress && !internal) |
| 824 | + if (!process_shared_preload_libraries_in_progress && |
| 825 | + GetInternalBgWorkerMain(worker) == NULL) |
826 | 826 | { |
827 | 827 | if (!IsUnderPostmaster) |
828 | 828 | ereport(LOG, |
@@ -1152,3 +1152,28 @@ TerminateBackgroundWorker(BackgroundWorkerHandle *handle) |
1152 | 1152 | if (signal_postmaster) |
1153 | 1153 | SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE); |
1154 | 1154 | } |
| 1155 | + |
| 1156 | +/* |
| 1157 | + * Search the known internal worker array and return its main function |
| 1158 | + * pointer if found. |
| 1159 | + * |
| 1160 | + * Returns NULL if not known internal worker. |
| 1161 | + */ |
| 1162 | +static bgworker_main_type |
| 1163 | +GetInternalBgWorkerMain(BackgroundWorker *worker) |
| 1164 | +{ |
| 1165 | + int i; |
| 1166 | + |
| 1167 | + /* Internal workers always have to use postgres as library name. */ |
| 1168 | + if (strncmp(worker->bgw_library_name, "postgres", BGW_MAXLEN) != 0) |
| 1169 | + return NULL; |
| 1170 | + |
| 1171 | + for (i = 0; InternalBGWorkers[i].bgw_function_name; i++) |
| 1172 | + { |
| 1173 | + if (strncmp(InternalBGWorkers[i].bgw_function_name, |
| 1174 | + worker->bgw_function_name, BGW_MAXLEN) == 0) |
| 1175 | + return InternalBGWorkers[i].bgw_main; |
| 1176 | + } |
| 1177 | + |
| 1178 | + return NULL; |
| 1179 | +} |
0 commit comments