Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 9b6e8d8

Browse files
committed
Don't use bgw_main even to specify in-core bgworker entrypoints.
On EXEC_BACKEND builds, this can fail if ASLR is in use. Backpatch to 9.5. On master, completely remove the bgw_main field completely, since there is no situation in which it is safe for an EXEC_BACKEND build. On 9.6 and 9.5, leave the field intact to avoid breaking things for third-party code that doesn't care about working under EXEC_BACKEND. Prior to 9.5, there are no in-core bgworker entrypoints. Petr Jelinek, reviewed by me. Discussion: http://postgr.es/m/09d8ad33-4287-a09b-a77f-77f8761adb5e@2ndquadrant.com
1 parent fa0d1fd commit 9b6e8d8

File tree

4 files changed

+73
-18
lines changed

4 files changed

+73
-18
lines changed

src/backend/access/transam/parallel.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ static dlist_head pcxt_list = DLIST_STATIC_INIT(pcxt_list);
109109
/* Private functions. */
110110
static void HandleParallelMessage(ParallelContext *pcxt, int i, StringInfo msg);
111111
static void ParallelExtensionTrampoline(dsm_segment *seg, shm_toc *toc);
112-
static void ParallelWorkerMain(Datum main_arg);
113112
static void WaitForParallelWorkersToExit(ParallelContext *pcxt);
114113

115114

@@ -456,7 +455,9 @@ LaunchParallelWorkers(ParallelContext *pcxt)
456455
BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION;
457456
worker.bgw_start_time = BgWorkerStart_ConsistentState;
458457
worker.bgw_restart_time = BGW_NEVER_RESTART;
459-
worker.bgw_main = ParallelWorkerMain;
458+
worker.bgw_main = NULL;
459+
sprintf(worker.bgw_library_name, "postgres");
460+
sprintf(worker.bgw_function_name, "ParallelWorkerMain");
460461
worker.bgw_main_arg = UInt32GetDatum(dsm_segment_handle(pcxt->seg));
461462
worker.bgw_notify_pid = MyProcPid;
462463
memset(&worker.bgw_extra, 0, BGW_EXTRALEN);
@@ -928,7 +929,7 @@ AtEOXact_Parallel(bool isCommit)
928929
/*
929930
* Main entrypoint for parallel workers.
930931
*/
931-
static void
932+
void
932933
ParallelWorkerMain(Datum main_arg)
933934
{
934935
dsm_segment *seg;

src/backend/postmaster/bgworker.c

+63-13
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "miscadmin.h"
1818
#include "libpq/pqsignal.h"
19+
#include "access/parallel.h"
1920
#include "postmaster/bgworker_internals.h"
2021
#include "postmaster/postmaster.h"
2122
#include "storage/barrier.h"
@@ -93,6 +94,25 @@ struct BackgroundWorkerHandle
9394

9495
static BackgroundWorkerArray *BackgroundWorkerData;
9596

97+
/*
98+
* List of internal background workers. These are used for mapping the
99+
* function name to actual function when building with EXEC_BACKEND and also
100+
* to allow these to be loaded outside of shared_preload_libraries.
101+
*/
102+
typedef struct InternalBGWorkerMain
103+
{
104+
char *bgw_function_name;
105+
bgworker_main_type bgw_main;
106+
} InternalBGWorkerMain;
107+
108+
static const InternalBGWorkerMain InternalBGWorkers[] = {
109+
{"ParallelWorkerMain", ParallelWorkerMain},
110+
/* Dummy entry marking end of the array. */
111+
{NULL, NULL}
112+
};
113+
114+
static bgworker_main_type GetInternalBgWorkerMain(BackgroundWorker *worker);
115+
96116
/*
97117
* Calculate shared memory needed.
98118
*/
@@ -695,22 +715,27 @@ StartBackgroundWorker(void)
695715
#endif
696716
}
697717

718+
/* For internal workers set the entry point to known function address. */
719+
entrypt = GetInternalBgWorkerMain(worker);
720+
698721
/*
699-
* If bgw_main is set, we use that value as the initial entrypoint.
700-
* However, if the library containing the entrypoint wasn't loaded at
701-
* postmaster startup time, passing it as a direct function pointer is not
702-
* possible. To work around that, we allow callers for whom a function
703-
* pointer is not available to pass a library name (which will be loaded,
704-
* if necessary) and a function name (which will be looked up in the named
722+
* Otherwise, if bgw_main is set, we use that value as the initial
723+
* entrypoint. This does not work well EXEC_BACKEND outside Windows but
724+
* we keep the logic for backwards compatibility. In other cases use
725+
* the entry point specified by library name (which will be loaded, if
726+
* necessary) and a function name (which will be looked up in the named
705727
* library).
706728
*/
707-
if (worker->bgw_main != NULL)
708-
entrypt = worker->bgw_main;
709-
else
710-
entrypt = (bgworker_main_type)
711-
load_external_function(worker->bgw_library_name,
712-
worker->bgw_function_name,
713-
true, NULL);
729+
if (entrypt == NULL)
730+
{
731+
if (worker->bgw_main != NULL)
732+
entrypt = worker->bgw_main;
733+
else
734+
entrypt = (bgworker_main_type)
735+
load_external_function(worker->bgw_library_name,
736+
worker->bgw_function_name,
737+
true, NULL);
738+
}
714739

715740
/*
716741
* Note that in normal processes, we would call InitPostgres here. For a
@@ -1050,3 +1075,28 @@ TerminateBackgroundWorker(BackgroundWorkerHandle *handle)
10501075
if (signal_postmaster)
10511076
SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE);
10521077
}
1078+
1079+
/*
1080+
* Search the known internal worker array and return its main function
1081+
* pointer if found.
1082+
*
1083+
* Returns NULL if not known internal worker.
1084+
*/
1085+
static bgworker_main_type
1086+
GetInternalBgWorkerMain(BackgroundWorker *worker)
1087+
{
1088+
int i;
1089+
1090+
/* Internal workers always have to use postgres as library name. */
1091+
if (strncmp(worker->bgw_library_name, "postgres", BGW_MAXLEN) != 0)
1092+
return NULL;
1093+
1094+
for (i = 0; InternalBGWorkers[i].bgw_function_name; i++)
1095+
{
1096+
if (strncmp(InternalBGWorkers[i].bgw_function_name,
1097+
worker->bgw_function_name, BGW_MAXLEN) == 0)
1098+
return InternalBGWorkers[i].bgw_main;
1099+
}
1100+
1101+
return NULL;
1102+
}

src/include/access/parallel.h

+2
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,6 @@ extern void AtEOXact_Parallel(bool isCommit);
6767
extern void AtEOSubXact_Parallel(bool isCommit, SubTransactionId mySubId);
6868
extern void ParallelWorkerReportLastRecEnd(XLogRecPtr last_xlog_end);
6969

70+
extern void ParallelWorkerMain(Datum main_arg);
71+
7072
#endif /* PARALLEL_H */

src/test/modules/worker_spi/worker_spi.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,9 @@ _PG_init(void)
346346
BGWORKER_BACKEND_DATABASE_CONNECTION;
347347
worker.bgw_start_time = BgWorkerStart_RecoveryFinished;
348348
worker.bgw_restart_time = BGW_NEVER_RESTART;
349-
worker.bgw_main = worker_spi_main;
349+
worker.bgw_main = NULL;
350+
sprintf(worker.bgw_library_name, "worker_spi");
351+
sprintf(worker.bgw_function_name, "worker_spi_main");
350352
worker.bgw_notify_pid = 0;
351353

352354
/*
@@ -377,7 +379,7 @@ worker_spi_launch(PG_FUNCTION_ARGS)
377379
BGWORKER_BACKEND_DATABASE_CONNECTION;
378380
worker.bgw_start_time = BgWorkerStart_RecoveryFinished;
379381
worker.bgw_restart_time = BGW_NEVER_RESTART;
380-
worker.bgw_main = NULL; /* new worker might not have library loaded */
382+
worker.bgw_main = NULL;
381383
sprintf(worker.bgw_library_name, "worker_spi");
382384
sprintf(worker.bgw_function_name, "worker_spi_main");
383385
snprintf(worker.bgw_name, BGW_MAXLEN, "worker %d", i);

0 commit comments

Comments
 (0)