mirror of
https://github.com/postgres/postgres.git
synced 2025-06-13 07:41:39 +03:00
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
This commit is contained in:
@ -106,7 +106,6 @@ static dlist_head pcxt_list = DLIST_STATIC_INIT(pcxt_list);
|
|||||||
static void HandleParallelMessage(ParallelContext *pcxt, int i, StringInfo msg);
|
static void HandleParallelMessage(ParallelContext *pcxt, int i, StringInfo msg);
|
||||||
static void ParallelErrorContext(void *arg);
|
static void ParallelErrorContext(void *arg);
|
||||||
static void ParallelExtensionTrampoline(dsm_segment *seg, shm_toc *toc);
|
static void ParallelExtensionTrampoline(dsm_segment *seg, shm_toc *toc);
|
||||||
static void ParallelWorkerMain(Datum main_arg);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -401,7 +400,9 @@ LaunchParallelWorkers(ParallelContext *pcxt)
|
|||||||
BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION;
|
BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION;
|
||||||
worker.bgw_start_time = BgWorkerStart_ConsistentState;
|
worker.bgw_start_time = BgWorkerStart_ConsistentState;
|
||||||
worker.bgw_restart_time = BGW_NEVER_RESTART;
|
worker.bgw_restart_time = BGW_NEVER_RESTART;
|
||||||
worker.bgw_main = ParallelWorkerMain;
|
worker.bgw_main = NULL;
|
||||||
|
sprintf(worker.bgw_library_name, "postgres");
|
||||||
|
sprintf(worker.bgw_function_name, "ParallelWorkerMain");
|
||||||
worker.bgw_main_arg = UInt32GetDatum(dsm_segment_handle(pcxt->seg));
|
worker.bgw_main_arg = UInt32GetDatum(dsm_segment_handle(pcxt->seg));
|
||||||
worker.bgw_notify_pid = MyProcPid;
|
worker.bgw_notify_pid = MyProcPid;
|
||||||
memset(&worker.bgw_extra, 0, BGW_EXTRALEN);
|
memset(&worker.bgw_extra, 0, BGW_EXTRALEN);
|
||||||
@ -834,7 +835,7 @@ AtEOXact_Parallel(bool isCommit)
|
|||||||
/*
|
/*
|
||||||
* Main entrypoint for parallel workers.
|
* Main entrypoint for parallel workers.
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
ParallelWorkerMain(Datum main_arg)
|
ParallelWorkerMain(Datum main_arg)
|
||||||
{
|
{
|
||||||
dsm_segment *seg;
|
dsm_segment *seg;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "libpq/pqsignal.h"
|
#include "libpq/pqsignal.h"
|
||||||
|
#include "access/parallel.h"
|
||||||
#include "postmaster/bgworker_internals.h"
|
#include "postmaster/bgworker_internals.h"
|
||||||
#include "postmaster/postmaster.h"
|
#include "postmaster/postmaster.h"
|
||||||
#include "storage/barrier.h"
|
#include "storage/barrier.h"
|
||||||
@ -93,6 +94,25 @@ struct BackgroundWorkerHandle
|
|||||||
|
|
||||||
static BackgroundWorkerArray *BackgroundWorkerData;
|
static BackgroundWorkerArray *BackgroundWorkerData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
typedef struct InternalBGWorkerMain
|
||||||
|
{
|
||||||
|
char *bgw_function_name;
|
||||||
|
bgworker_main_type bgw_main;
|
||||||
|
} InternalBGWorkerMain;
|
||||||
|
|
||||||
|
static const InternalBGWorkerMain InternalBGWorkers[] = {
|
||||||
|
{"ParallelWorkerMain", ParallelWorkerMain},
|
||||||
|
/* Dummy entry marking end of the array. */
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static bgworker_main_type GetInternalBgWorkerMain(BackgroundWorker *worker);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate shared memory needed.
|
* Calculate shared memory needed.
|
||||||
*/
|
*/
|
||||||
@ -695,15 +715,19 @@ StartBackgroundWorker(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For internal workers set the entry point to known function address. */
|
||||||
|
entrypt = GetInternalBgWorkerMain(worker);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If bgw_main is set, we use that value as the initial entrypoint.
|
* Otherwise, if bgw_main is set, we use that value as the initial
|
||||||
* However, if the library containing the entrypoint wasn't loaded at
|
* entrypoint. This does not work well EXEC_BACKEND outside Windows but
|
||||||
* postmaster startup time, passing it as a direct function pointer is not
|
* we keep the logic for backwards compatibility. In other cases use
|
||||||
* possible. To work around that, we allow callers for whom a function
|
* the entry point specified by library name (which will be loaded, if
|
||||||
* pointer is not available to pass a library name (which will be loaded,
|
* necessary) and a function name (which will be looked up in the named
|
||||||
* if necessary) and a function name (which will be looked up in the named
|
|
||||||
* library).
|
* library).
|
||||||
*/
|
*/
|
||||||
|
if (entrypt == NULL)
|
||||||
|
{
|
||||||
if (worker->bgw_main != NULL)
|
if (worker->bgw_main != NULL)
|
||||||
entrypt = worker->bgw_main;
|
entrypt = worker->bgw_main;
|
||||||
else
|
else
|
||||||
@ -711,6 +735,7 @@ StartBackgroundWorker(void)
|
|||||||
load_external_function(worker->bgw_library_name,
|
load_external_function(worker->bgw_library_name,
|
||||||
worker->bgw_function_name,
|
worker->bgw_function_name,
|
||||||
true, NULL);
|
true, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note that in normal processes, we would call InitPostgres here. For a
|
* Note that in normal processes, we would call InitPostgres here. For a
|
||||||
@ -1078,3 +1103,28 @@ TerminateBackgroundWorker(BackgroundWorkerHandle *handle)
|
|||||||
if (signal_postmaster)
|
if (signal_postmaster)
|
||||||
SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE);
|
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;
|
||||||
|
}
|
||||||
|
@ -65,4 +65,6 @@ extern void AtEOXact_Parallel(bool isCommit);
|
|||||||
extern void AtEOSubXact_Parallel(bool isCommit, SubTransactionId mySubId);
|
extern void AtEOSubXact_Parallel(bool isCommit, SubTransactionId mySubId);
|
||||||
extern void ParallelWorkerReportLastRecEnd(XLogRecPtr last_xlog_end);
|
extern void ParallelWorkerReportLastRecEnd(XLogRecPtr last_xlog_end);
|
||||||
|
|
||||||
|
extern void ParallelWorkerMain(Datum main_arg);
|
||||||
|
|
||||||
#endif /* PARALLEL_H */
|
#endif /* PARALLEL_H */
|
||||||
|
@ -346,7 +346,9 @@ _PG_init(void)
|
|||||||
BGWORKER_BACKEND_DATABASE_CONNECTION;
|
BGWORKER_BACKEND_DATABASE_CONNECTION;
|
||||||
worker.bgw_start_time = BgWorkerStart_RecoveryFinished;
|
worker.bgw_start_time = BgWorkerStart_RecoveryFinished;
|
||||||
worker.bgw_restart_time = BGW_NEVER_RESTART;
|
worker.bgw_restart_time = BGW_NEVER_RESTART;
|
||||||
worker.bgw_main = worker_spi_main;
|
worker.bgw_main = NULL;
|
||||||
|
sprintf(worker.bgw_library_name, "worker_spi");
|
||||||
|
sprintf(worker.bgw_function_name, "worker_spi_main");
|
||||||
worker.bgw_notify_pid = 0;
|
worker.bgw_notify_pid = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -377,7 +379,7 @@ worker_spi_launch(PG_FUNCTION_ARGS)
|
|||||||
BGWORKER_BACKEND_DATABASE_CONNECTION;
|
BGWORKER_BACKEND_DATABASE_CONNECTION;
|
||||||
worker.bgw_start_time = BgWorkerStart_RecoveryFinished;
|
worker.bgw_start_time = BgWorkerStart_RecoveryFinished;
|
||||||
worker.bgw_restart_time = BGW_NEVER_RESTART;
|
worker.bgw_restart_time = BGW_NEVER_RESTART;
|
||||||
worker.bgw_main = NULL; /* new worker might not have library loaded */
|
worker.bgw_main = NULL;
|
||||||
sprintf(worker.bgw_library_name, "worker_spi");
|
sprintf(worker.bgw_library_name, "worker_spi");
|
||||||
sprintf(worker.bgw_function_name, "worker_spi_main");
|
sprintf(worker.bgw_function_name, "worker_spi_main");
|
||||||
snprintf(worker.bgw_name, BGW_MAXLEN, "worker %d", i);
|
snprintf(worker.bgw_name, BGW_MAXLEN, "worker %d", i);
|
||||||
|
Reference in New Issue
Block a user