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

Lines changed: 4 additions & 3 deletions
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

Lines changed: 63 additions & 13 deletions
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

Lines changed: 2 additions & 0 deletions
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

Lines changed: 4 additions & 2 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy