Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cvSu6-0004r9-Iq for pgsql-hackers@arkaria.postgresql.org; Tue, 04 Apr 2017 18:10:06 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.84_2) (envelope-from ) id 1cvSu6-0007Y3-15 for pgsql-hackers@arkaria.postgresql.org; Tue, 04 Apr 2017 18:10:06 +0000 Received: from makus.postgresql.org ([2001:4800:1501:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1cvSsY-0004vu-NA for pgsql-hackers@postgresql.org; Tue, 04 Apr 2017 18:08:31 +0000 Received: from mail-wr0-x236.google.com ([2a00:1450:400c:c0c::236]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.84_2) (envelope-from ) id 1cvSsR-0006R5-2z for pgsql-hackers@postgresql.org; Tue, 04 Apr 2017 18:08:29 +0000 Received: by mail-wr0-x236.google.com with SMTP id t20so16749681wra.1 for ; Tue, 04 Apr 2017 11:08:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=2ndquadrant-com.20150623.gappssmtp.com; s=20150623; h=subject:to:references:cc:from:message-id:date:user-agent :mime-version:in-reply-to; bh=hJna9v/bGUBHz5wssRxtLNrE5WHNay+CVA91We5rJC4=; b=XWCewpc0g0hOn94xc5PBMHqNpjR0yT2LiEWtW9Av/3eUY0aEGB8F+7E9sD8RXhTjBX krp9tWvpbuugtTe90CDRUrzgDsvzIDs1rF66qILVVm+JJ96rf7UXvJ9szxNawLgUDU5x W48Xju+0aBxez22t0P1Ff62kBBukbDvo1SQbIbAbJkKEfHU4bIM1ta5FzEJ1F9cXnVVN KS9sNcTXJRfM6odfXdV+mQrQDuZbfJHafHuBhEkxsL4OxqptXwpmuWeaOBpemiHnmFLj a9Pbwoxj2c/KYzqzBzEVp/TTjs0EKkdgKsUkiyc1eP5MA3Bfous3aB9+YIp/hEB3O/C+ Woew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:references:cc:from:message-id:date :user-agent:mime-version:in-reply-to; bh=hJna9v/bGUBHz5wssRxtLNrE5WHNay+CVA91We5rJC4=; b=WhuZaXUA5bp4KJ0DvLs+NL7r6mMG2GzkRrIFakCN5jTyqEp0kg/hMhy/Rqn0lVvVka uP54/sn1BgOfv4sMtXm0KfKvcpzhlGg20JLcNFgeqpLYoSQIyVzIWUMvyNl+I/7ooAm8 B247eCItZKyNeeZVMpebbHYQGWI88f6ARmUyJkNhGsf8bnmnSi1BieGp1de+2DEfJt5E wBT+lVb14ZTzmR9lvcgqK5ekohJBe2iwA8lfkmltE8eo9ckgGK50ef4vU9YH9rfYNesZ izZM5xUPkbetWN4Jg29PNZS8VPIri1SIsZhFRadEPeufb0yF51yCdA/GjrcBmGMPFEOW xJzA== X-Gm-Message-State: AFeK/H2zoPlPmBw6xH/uyjXgSS2XOd+Qovd1GBDeP2vEt2S4VITdWi4QrU8frcmaOZbDv+bL X-Received: by 10.223.139.146 with SMTP id o18mr21921804wra.61.1491329301479; Tue, 04 Apr 2017 11:08:21 -0700 (PDT) Received: from [192.168.86.152] (092-111-191-154.static.chello.nl. [92.111.191.154]) by smtp.gmail.com with ESMTPSA id w93sm23269193wrb.3.2017.04.04.11.08.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Apr 2017 11:08:19 -0700 (PDT) Subject: Re: logical replication launcher crash on buildfarm To: Andres Freund , Robert Haas References: <0471e978-b121-ad2f-2879-f1694d9a5ce7@2ndquadrant.com> <2124fb62-2393-8525-4fe9-b95b1b689d09@2ndquadrant.com> <09d8ad33-4287-a09b-a77f-77f8761adb5e@2ndquadrant.com> <8ebd3aa3-55eb-1106-7c10-7e7579f94582@2ndquadrant.com> <20170401021928.47zjjryhty5kdzqz@alap3.anarazel.de> Cc: "pgsql-hackers@postgresql.org" , Petr Jelinek , Peter Eisentraut From: Petr Jelinek Message-ID: <548f9c1d-eafa-e3fa-9da8-f0cc2f654e60@2ndquadrant.com> Date: Tue, 4 Apr 2017 20:08:17 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.7.0 MIME-Version: 1.0 In-Reply-To: <20170401021928.47zjjryhty5kdzqz@alap3.anarazel.de> Content-Type: multipart/mixed; boundary="------------03DFBEDAE6468671E8B87E16" X-Pg-Spam-Score: -1.9 (-) List-Archive: List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Mailing-List: pgsql-hackers Precedence: bulk Sender: pgsql-hackers-owner@postgresql.org This is a multi-part message in MIME format. --------------03DFBEDAE6468671E8B87E16 Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit So this is what I came up with on plane. Generalized the loading functionality into load_library_function which that can load either known postgres functions or call load_external_function. I am not quite sure if fmgr.c is best place to put it, but I didn't want to include stuff from executor in bgworker.c. I was thinking about putting it to dfmgr.c (as that's where load_external_function) but again seemed weird to including executor there. As with previous patch, 9.6 will need quite different patch as we need to keep compatibility there, but since I am traveling I think it's better to share what I have so far. -- Petr Jelinek http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Training & Services --------------03DFBEDAE6468671E8B87E16 Content-Type: text/x-diff; name="dont-pass-funtion-pointers-to-new-processes.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="dont-pass-funtion-pointers-to-new-processes.diff" diff --git a/src/backend/access/transam/README.parallel b/src/backend/acces= s/transam/README.parallel index db9ac3d..b360887 100644 --- a/src/backend/access/transam/README.parallel +++ b/src/backend/access/transam/README.parallel @@ -198,7 +198,7 @@ pattern looks like this: =20 EnterParallelMode(); /* prohibit unsafe state changes */ =20 - pcxt =3D CreateParallelContext(entrypoint, nworkers); + pcxt =3D CreateParallelContext("library_name", "function_name", nworkers); =20 /* Allow space for application-specific data here. */ shm_toc_estimate_chunk(&pcxt->estimator, size); diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/tra= nsam/parallel.c index b3d3853..326d4f9 100644 --- a/src/backend/access/transam/parallel.c +++ b/src/backend/access/transam/parallel.c @@ -61,7 +61,7 @@ #define PARALLEL_KEY_TRANSACTION_SNAPSHOT UINT64CONST(0xFFFFFFFFFFFF0006) #define PARALLEL_KEY_ACTIVE_SNAPSHOT UINT64CONST(0xFFFFFFFFFFFF0007) #define PARALLEL_KEY_TRANSACTION_STATE UINT64CONST(0xFFFFFFFFFFFF0008) -#define PARALLEL_KEY_EXTENSION_TRAMPOLINE UINT64CONST(0xFFFFFFFFFFFF0009) +#define PARALLEL_KEY_ENTRYPOINT UINT64CONST(0xFFFFFFFFFFFF0009) =20 /* Fixed-size parallel state. */ typedef struct FixedParallelState @@ -77,9 +77,6 @@ typedef struct FixedParallelState pid_t parallel_master_pid; BackendId parallel_master_backend_id; =20 - /* Entrypoint for parallel workers. */ - parallel_worker_main_type entrypoint; - /* Mutex protects remaining fields. */ slock_t mutex; =20 @@ -109,7 +106,6 @@ static dlist_head pcxt_list =3D DLIST_STATIC_INIT(pcxt_= list); =20 /* Private functions. */ static void HandleParallelMessage(ParallelContext *pcxt, int i, StringInfo= msg); -static void ParallelExtensionTrampoline(dsm_segment *seg, shm_toc *toc); static void WaitForParallelWorkersToExit(ParallelContext *pcxt); =20 =20 @@ -119,7 +115,8 @@ static void WaitForParallelWorkersToExit(ParallelContex= t *pcxt); * destroyed before exiting the current subtransaction. */ ParallelContext * -CreateParallelContext(parallel_worker_main_type entrypoint, int nworkers) +CreateParallelContext(const char *library_name, const char *function_name, + int nworkers) { MemoryContext oldcontext; ParallelContext *pcxt; @@ -152,7 +149,8 @@ CreateParallelContext(parallel_worker_main_type entrypo= int, int nworkers) pcxt =3D palloc0(sizeof(ParallelContext)); pcxt->subid =3D GetCurrentSubTransactionId(); pcxt->nworkers =3D nworkers; - pcxt->entrypoint =3D entrypoint; + pcxt->library_name =3D pstrdup(library_name); + pcxt->function_name =3D pstrdup(function_name); pcxt->error_context_stack =3D error_context_stack; shm_toc_initialize_estimator(&pcxt->estimator); dlist_push_head(&pcxt_list, &pcxt->node); @@ -164,33 +162,6 @@ CreateParallelContext(parallel_worker_main_type entryp= oint, int nworkers) } =20 /* - * Establish a new parallel context that calls a function provided by an - * extension. This works around the fact that the library might get mapped - * at a different address in each backend. - */ -ParallelContext * -CreateParallelContextForExternalFunction(char *library_name, - char *function_name, - int nworkers) -{ - MemoryContext oldcontext; - ParallelContext *pcxt; - - /* We might be running in a very short-lived memory context. */ - oldcontext =3D MemoryContextSwitchTo(TopTransactionContext); - - /* Create the context. */ - pcxt =3D CreateParallelContext(ParallelExtensionTrampoline, nworkers); - pcxt->library_name =3D pstrdup(library_name); - pcxt->function_name =3D pstrdup(function_name); - - /* Restore previous memory context. */ - MemoryContextSwitchTo(oldcontext); - - return pcxt; -} - -/* * Establish the dynamic shared memory segment for a parallel context and * copy state and other bookkeeping information that will be needed by * parallel workers into it. @@ -249,15 +220,10 @@ InitializeParallelDSM(ParallelContext *pcxt) pcxt->nworkers)); shm_toc_estimate_keys(&pcxt->estimator, 1); =20 - /* Estimate how much we'll need for extension entrypoint info. */ - if (pcxt->library_name !=3D NULL) - { - Assert(pcxt->entrypoint =3D=3D ParallelExtensionTrampoline); - Assert(pcxt->function_name !=3D NULL); - shm_toc_estimate_chunk(&pcxt->estimator, strlen(pcxt->library_name) - + strlen(pcxt->function_name) + 2); - shm_toc_estimate_keys(&pcxt->estimator, 1); - } + /* Estimate how much we'll need for the entrypoint info. */ + shm_toc_estimate_chunk(&pcxt->estimator, strlen(pcxt->library_name) + + strlen(pcxt->function_name) + 2); + shm_toc_estimate_keys(&pcxt->estimator, 1); } =20 /* @@ -297,7 +263,6 @@ InitializeParallelDSM(ParallelContext *pcxt) fps->parallel_master_pgproc =3D MyProc; fps->parallel_master_pid =3D MyProcPid; fps->parallel_master_backend_id =3D MyBackendId; - fps->entrypoint =3D pcxt->entrypoint; SpinLockInit(&fps->mutex); fps->last_xlog_end =3D 0; shm_toc_insert(pcxt->toc, PARALLEL_KEY_FIXED, fps); @@ -312,6 +277,8 @@ InitializeParallelDSM(ParallelContext *pcxt) char *asnapspace; char *tstatespace; char *error_queue_space; + char *entrypointstate; + Size lnamelen; =20 /* Serialize shared libraries we have loaded. */ libraryspace =3D shm_toc_allocate(pcxt->toc, library_len); @@ -368,19 +335,18 @@ InitializeParallelDSM(ParallelContext *pcxt) } shm_toc_insert(pcxt->toc, PARALLEL_KEY_ERROR_QUEUE, error_queue_space); =20 - /* Serialize extension entrypoint information. */ - if (pcxt->library_name !=3D NULL) - { - Size lnamelen =3D strlen(pcxt->library_name); - char *extensionstate; - - extensionstate =3D shm_toc_allocate(pcxt->toc, lnamelen - + strlen(pcxt->function_name) + 2); - strcpy(extensionstate, pcxt->library_name); - strcpy(extensionstate + lnamelen + 1, pcxt->function_name); - shm_toc_insert(pcxt->toc, PARALLEL_KEY_EXTENSION_TRAMPOLINE, - extensionstate); - } + /* + * Serialize extension entrypoint information. It's unsafe to pass + * function pointers across parallel processes as the function pointer + * may be different in new process in EXEC_BACKEND builds so we + * always pass library and function name. + */ + lnamelen =3D strlen(pcxt->library_name); + entrypointstate =3D shm_toc_allocate(pcxt->toc, lnamelen + + strlen(pcxt->function_name) + 2); + strcpy(entrypointstate, pcxt->library_name); + strcpy(entrypointstate + lnamelen + 1, pcxt->function_name); + shm_toc_insert(pcxt->toc, PARALLEL_KEY_ENTRYPOINT, entrypointstate); } =20 /* Restore previous memory context. */ @@ -946,7 +912,11 @@ ParallelWorkerMain(Datum main_arg) char *tsnapspace; char *asnapspace; char *tstatespace; + char *entrypointstate; + char *library_name; + char *function_name; StringInfoData msgbuf; + parallel_worker_main_type entrypt; =20 /* Set flag to indicate that we're initializing a parallel worker. */ InitializingParallelWorker =3D true; @@ -1077,6 +1047,15 @@ ParallelWorkerMain(Datum main_arg) Assert(asnapspace !=3D NULL); PushActiveSnapshot(RestoreSnapshot(asnapspace)); =20 + /* Load the entry point. */ + entrypointstate =3D shm_toc_lookup(toc, PARALLEL_KEY_ENTRYPOINT); + Assert(entrypointstate !=3D NULL); + library_name =3D entrypointstate; + function_name =3D entrypointstate + strlen(library_name) + 1; + + entrypt =3D (parallel_worker_main_type) + load_library_function(library_name, function_name); + /* * We've changed which tuples we can see, and must therefore invalidate * system caches. @@ -1102,11 +1081,8 @@ ParallelWorkerMain(Datum main_arg) =20 /* * Time to do the real work: invoke the caller-supplied code. - * - * If you get a crash at this line, see the comments for - * ParallelExtensionTrampoline. */ - fps->entrypoint(seg, toc); + entrypt(seg, toc); =20 /* Must exit parallel mode to pop active snapshot. */ ExitParallelMode(); @@ -1122,33 +1098,6 @@ ParallelWorkerMain(Datum main_arg) } =20 /* - * It's unsafe for the entrypoint invoked by ParallelWorkerMain to be a - * function living in a dynamically loaded module, because the module might - * not be loaded in every process, or might be loaded but not at the same - * address. To work around that problem, CreateParallelContextForExtensio= n() - * arranges to call this function rather than calling the extension-provid= ed - * function directly; and this function then looks up the real entrypoint = and - * calls it. - */ -static void -ParallelExtensionTrampoline(dsm_segment *seg, shm_toc *toc) -{ - char *extensionstate; - char *library_name; - char *function_name; - parallel_worker_main_type entrypt; - - extensionstate =3D shm_toc_lookup(toc, PARALLEL_KEY_EXTENSION_TRAMPOLINE); - Assert(extensionstate !=3D NULL); - library_name =3D extensionstate; - function_name =3D extensionstate + strlen(library_name) + 1; - - entrypt =3D (parallel_worker_main_type) - load_external_function(library_name, function_name, true, NULL); - entrypt(seg, toc); -} - -/* * Update shared memory with the ending location of the last WAL record we * wrote, if it's greater than the value already stored there. */ diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/exe= cParallel.c index 469a32c..49ea1e0 100644 --- a/src/backend/executor/execParallel.c +++ b/src/backend/executor/execParallel.c @@ -112,8 +112,7 @@ static shm_mq_handle **ExecParallelSetupTupleQueues(Par= allelContext *pcxt, static bool ExecParallelRetrieveInstrumentation(PlanState *planstate, SharedExecutorInstrumentation *instrumentation); =20 -/* Helper functions that run in the parallel worker. */ -static void ParallelQueryMain(dsm_segment *seg, shm_toc *toc); +/* Helper function that run in the parallel worker. */ static DestReceiver *ExecParallelGetReceiver(dsm_segment *seg, shm_toc *to= c); =20 /* @@ -393,7 +392,7 @@ ExecInitParallelPlan(PlanState *planstate, EState *esta= te, int nworkers) pstmt_data =3D ExecSerializePlan(planstate->plan, estate); =20 /* Create a parallel context. */ - pcxt =3D CreateParallelContext(ParallelQueryMain, nworkers); + pcxt =3D CreateParallelContext("postgres", "ParallelQueryMain", nworkers); pei->pcxt =3D pcxt; =20 /* @@ -814,7 +813,7 @@ ExecParallelInitializeWorker(PlanState *planstate, shm_= toc *toc) * to do this are also stored in the dsm_segment and can be accessed throu= gh * the shm_toc. */ -static void +void ParallelQueryMain(dsm_segment *seg, shm_toc *toc) { BufferUsage *buffer_usage; diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgw= orker.c index 0823317..0a9ca98 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -15,14 +15,11 @@ #include =20 #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" @@ -111,27 +108,6 @@ struct BackgroundWorkerHandle static BackgroundWorkerArray *BackgroundWorkerData; =20 /* - * List of internal background workers. These are used for mapping the - * function name to actual function when building with EXEC_BACKEND and al= so - * 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[] =3D { - {"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. */ Size @@ -776,18 +752,14 @@ StartBackgroundWorker(void) } =20 /* - * 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). + * Load the function. For internal workers the function will be loaded + * according to known function map (see fmgr.c). 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). */ - entrypt =3D GetInternalBgWorkerMain(worker); - - if (entrypt =3D=3D NULL) - entrypt =3D (bgworker_main_type) - load_external_function(worker->bgw_library_name, - worker->bgw_function_name, - true, NULL); + entrypt =3D (bgworker_main_type) + load_library_function(worker->bgw_library_name, + worker->bgw_function_name); =20 /* * Note that in normal processes, we would call InitPostgres here. For a @@ -806,10 +778,11 @@ StartBackgroundWorker(void) } =20 /* - * Register a new background worker while processing shared_preload_librar= ies. + * Register a new static background worker. * - * This can only be called in the _PG_init function of a module library - * that's loaded by shared_preload_libraries; otherwise it has no effect. + * This can only be called directly from postmaster or in the _PG_init + * function of a module library that's loaded by shared_preload_libraries; + * otherwise it will have no effect. */ void RegisterBackgroundWorker(BackgroundWorker *worker) @@ -822,7 +795,7 @@ RegisterBackgroundWorker(BackgroundWorker *worker) (errmsg("registering background worker \"%s\"", worker->bgw_name))); =20 if (!process_shared_preload_libraries_in_progress && - GetInternalBgWorkerMain(worker) =3D=3D NULL) + strcmp(worker->bgw_library_name, "postgres") !=3D 0) { if (!IsUnderPostmaster) ereport(LOG, @@ -1152,28 +1125,3 @@ TerminateBackgroundWorker(BackgroundWorkerHandle *ha= ndle) 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) !=3D 0) - return NULL; - - for (i =3D 0; InternalBGWorkers[i].bgw_function_name; i++) - { - if (strncmp(InternalBGWorkers[i].bgw_function_name, - worker->bgw_function_name, BGW_MAXLEN) =3D=3D 0) - return InternalBGWorkers[i].bgw_main; - } - - return NULL; -} diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c index 68d2110..c23db6a 100644 --- a/src/backend/utils/fmgr/fmgr.c +++ b/src/backend/utils/fmgr/fmgr.c @@ -15,14 +15,18 @@ =20 #include "postgres.h" =20 +#include "access/parallel.h" #include "access/tuptoaster.h" #include "catalog/pg_language.h" #include "catalog/pg_proc.h" +#include "executor/execParallel.h" #include "executor/functions.h" #include "lib/stringinfo.h" #include "miscadmin.h" #include "nodes/nodeFuncs.h" #include "pgstat.h" +#include "replication/logicallauncher.h" +#include "replication/logicalworker.h" #include "utils/acl.h" #include "utils/builtins.h" #include "utils/fmgrtab.h" @@ -61,6 +65,25 @@ static void record_C_func(HeapTuple procedureTuple, PGFunction user_fn, const Pg_finfo_record *inforec); static Datum fmgr_security_definer(PG_FUNCTION_ARGS); =20 +/* + * These are used for mapping the function name to actual function when + * building with EXEC_BACKEND and also to allow bgworkers using these outs= ide + * of shared_preload_libraries. + */ +typedef struct KnownFunctionPointer +{ + char *fn_name; + void *fn_addr; +} KnownFunctionPointer; + +static const KnownFunctionPointer known_functions_map[] =3D { + {"ParallelWorkerMain", ParallelWorkerMain}, + {"ParallelQueryMain", ParallelQueryMain}, + {"ApplyLauncherMain", ApplyLauncherMain}, + {"ApplyWorkerMain", ApplyWorkerMain}, + /* Dummy entry marking end of the array. */ + {NULL, NULL} +}; =20 /* * Lookup routines for builtin-function table. We can search by either Oid @@ -691,6 +714,36 @@ fmgr_security_definer(PG_FUNCTION_ARGS) return result; } =20 +/* + * This is similar to load_external_function (which is may call) but will + * also try to match funct name to internal known functions map when asked= to + * load postgres function. + */ +void * +load_library_function(char *libraryname, char *funcname) +{ + /* + * If the function is to be loaded from postgres itself, search the known + * functions map. + */ + if (strcmp(libraryname, "postgres") =3D=3D 0) + { + int i; + + for (i =3D 0; known_functions_map[i].fn_name; i++) + { + if (strcmp(known_functions_map[i].fn_name, + funcname) =3D=3D 0) + return known_functions_map[i].fn_addr; + } + + /* We can only reach this by programming error. */ + elog(ERROR, "internal function \"%s\" not found", funcname); + } + + /* Otherwise load from external library. */ + return load_external_function(libraryname, funcname, true, NULL); +} =20 /*------------------------------------------------------------------------- * Support routines for callers of fmgr-compatible functions diff --git a/src/include/access/parallel.h b/src/include/access/parallel.h index 5065a38..b869727 100644 --- a/src/include/access/parallel.h +++ b/src/include/access/parallel.h @@ -52,8 +52,7 @@ extern bool InitializingParallelWorker; =20 #define IsParallelWorker() (ParallelWorkerNumber >=3D 0) =20 -extern ParallelContext *CreateParallelContext(parallel_worker_main_type en= trypoint, int nworkers); -extern ParallelContext *CreateParallelContextForExternalFunction(char *lib= rary_name, char *function_name, int nworkers); +extern ParallelContext *CreateParallelContext(const char *library_name, co= nst char *function_name, int nworkers); extern void InitializeParallelDSM(ParallelContext *pcxt); extern void ReinitializeParallelDSM(ParallelContext *pcxt); extern void LaunchParallelWorkers(ParallelContext *pcxt); diff --git a/src/include/executor/execParallel.h b/src/include/executor/exe= cParallel.h index 8bc4270..0b7ca59 100644 --- a/src/include/executor/execParallel.h +++ b/src/include/executor/execParallel.h @@ -38,4 +38,6 @@ extern void ExecParallelFinish(ParallelExecutorInfo *pei); extern void ExecParallelCleanup(ParallelExecutorInfo *pei); extern void ExecParallelReinitialize(ParallelExecutorInfo *pei); =20 +extern void ParallelQueryMain(dsm_segment *seg, shm_toc *toc); + #endif /* EXECPARALLEL_H */ diff --git a/src/include/fmgr.h b/src/include/fmgr.h index 0c695e2..2e41edf 100644 --- a/src/include/fmgr.h +++ b/src/include/fmgr.h @@ -667,6 +667,7 @@ extern bool get_fn_expr_arg_stable(FmgrInfo *flinfo, in= t argnum); extern bool get_call_expr_arg_stable(fmNodePtr expr, int argnum); extern bool get_fn_expr_variadic(FmgrInfo *flinfo); extern bool CheckFunctionValidatorAccess(Oid validatorOid, Oid functionOid= ); +extern void *load_library_function(char *libraryname, char *funcname); =20 /* * Routines in dfmgr.c --------------03DFBEDAE6468671E8B87E16 Content-Type: text/plain Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers --------------03DFBEDAE6468671E8B87E16--