summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2006-08-08 19:15:09 +0000
committerTom Lane2006-08-08 19:15:09 +0000
commit2f206b5ec93c755d98c472c89781023d5813e2c3 (patch)
tree70a6c971d14e475cdfe8989abcd7325890ec77ad
parentd1452f101951601c6443ad36565fda6c5462a019 (diff)
Add a feature for automatic initialization and finalization of dynamically
loaded libraries: call functions _PG_init() and _PG_fini() if the library defines such symbols. Hence we no longer need to specify an initialization function in preload_libraries: we can assume that the library used the _PG_init() convention, instead. This removes one source of pilot error in use of preloaded libraries. Original patch by Ralf Engelschall, preload_libraries changes by me.
-rw-r--r--doc/src/sgml/config.sgml31
-rw-r--r--doc/src/sgml/xfunc.sgml97
-rw-r--r--src/backend/postmaster/postmaster.c9
-rw-r--r--src/backend/utils/fmgr/dfmgr.c25
-rw-r--r--src/backend/utils/init/miscinit.c58
-rw-r--r--src/include/miscadmin.h4
-rw-r--r--src/include/postmaster/postmaster.h1
-rw-r--r--src/pl/plperl/plperl.c46
-rw-r--r--src/pl/plpgsql/src/pl_handler.c38
-rw-r--r--src/pl/plpgsql/src/plpgsql.h2
-rw-r--r--src/pl/plpython/plpython.c45
-rw-r--r--src/pl/tcl/pltcl.c36
12 files changed, 166 insertions, 226 deletions
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index ea9f439066..c19b5d7e1e 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -957,39 +957,36 @@ SET ENABLE_SEQSCAN TO OFF;
<listitem>
<para>
This variable specifies one or more shared libraries that are
- to be preloaded at server start. A parameterless
- initialization function can optionally be called for each
- library. To specify that, add a colon and the name of the
- initialization function after the library name. For example
- <literal>'$libdir/mylib:mylib_init'</literal> would cause
- <literal>mylib</> to be preloaded and <literal>mylib_init</>
- to be executed. If more than one library is to be loaded,
- separate their names with commas.
- </para>
-
- <para>
- If a specified library or initialization function is not found,
- the server will fail to start.
+ to be preloaded at server start. If more than one library is to be
+ loaded, separate their names with commas. For example,
+ <literal>'$libdir/mylib'</literal> would cause
+ <literal>mylib.so</> (or on some platforms,
+ <literal>mylib.sl</>) to be preloaded from the installation's
+ standard library directory.
</para>
<para>
<productname>PostgreSQL</productname> procedural language
libraries can be preloaded in this way, typically by using the
- syntax <literal>'$libdir/plXXX:plXXX_init'</literal> where
+ syntax <literal>'$libdir/plXXX'</literal> where
<literal>XXX</literal> is <literal>pgsql</>, <literal>perl</>,
<literal>tcl</>, or <literal>python</>.
</para>
<para>
- By preloading a shared library (and initializing it if
- applicable), the library startup time is avoided when the
- library is first used. However, the time to start each new
+ By preloading a shared library, the library startup time is avoided
+ when the library is first used. However, the time to start each new
server process may increase slightly, even if that process never
uses the library. So this parameter is recommended only for
libraries that will be used in most sessions.
</para>
<para>
+ If a specified library is not found,
+ the server will fail to start.
+ </para>
+
+ <para>
Every PostgreSQL-supported library has a <quote>magic
block</> that is checked to guarantee compatibility.
For this reason, non-PostgreSQL libraries cannot be
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index 9b978aff43..d4f3a49e5c 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -1149,6 +1149,15 @@ CREATE FUNCTION square_root(double precision) RETURNS double precision
</para>
<para>
+ It is recommended to locate shared libraries either relative to
+ <literal>$libdir</literal> or through the dynamic library path.
+ This simplifies version upgrades if the new installation is at a
+ different location. The actual directory that
+ <literal>$libdir</literal> stands for can be found out with the
+ command <literal>pg_config --pkglibdir</literal>.
+ </para>
+
+ <para>
The user ID the <productname>PostgreSQL</productname> server runs
as must be able to traverse the path to the file you intend to
load. Making the file or a higher-level directory not readable
@@ -1173,6 +1182,32 @@ CREATE FUNCTION square_root(double precision) RETURNS double precision
</para>
</note>
+ <indexterm zone="xfunc-c-dynload">
+ <primary>magic block</primary>
+ </indexterm>
+
+ <para>
+ To ensure that a dynamically loaded object file is not loaded into an
+ incompatible server, <productname>PostgreSQL</productname> checks that the
+ file contains a <quote>magic block</> with the appropriate contents.
+ This allows the server to detect obvious incompatibilities, such as code
+ compiled for a different major version of
+ <productname>PostgreSQL</productname>. A magic block is required as of
+ <productname>PostgreSQL</productname> 8.2. To include a magic block,
+ write this in one (and only one) of the module source files, after having
+ included the header <filename>fmgr.h</>:
+
+<programlisting>
+#ifdef PG_MODULE_MAGIC
+PG_MODULE_MAGIC;
+#endif
+</programlisting>
+
+ The <literal>#ifdef</> test can be omitted if the code doesn't
+ need to compile against pre-8.2 <productname>PostgreSQL</productname>
+ releases.
+ </para>
+
<para>
After it is used for the first time, a dynamically loaded object
file is retained in memory. Future calls in the same session to
@@ -1183,13 +1218,31 @@ CREATE FUNCTION square_root(double precision) RETURNS double precision
fresh session.
</para>
+ <indexterm zone="xfunc-c-dynload">
+ <primary>_PG_init</primary>
+ </indexterm>
+ <indexterm zone="xfunc-c-dynload">
+ <primary>_PG_fini</primary>
+ </indexterm>
+ <indexterm zone="xfunc-c-dynload">
+ <primary>library initialization function</primary>
+ </indexterm>
+ <indexterm zone="xfunc-c-dynload">
+ <primary>library finalization function</primary>
+ </indexterm>
+
<para>
- It is recommended to locate shared libraries either relative to
- <literal>$libdir</literal> or through the dynamic library path.
- This simplifies version upgrades if the new installation is at a
- different location. The actual directory that
- <literal>$libdir</literal> stands for can be found out with the
- command <literal>pg_config --pkglibdir</literal>.
+ Optionally, a dynamically loaded file can contain initialization and
+ finalization functions. If the file includes a function named
+ <literal>_PG_init</>, that function will be called immediately after
+ loading the file. The function receives no parameters and should
+ return void. If the file includes a function named
+ <literal>_PG_fini</>, that function will be called immediately before
+ unloading the file. Likewise, the function receives no parameters and
+ should return void. Note that <literal>_PG_fini</> will only be called
+ during an unload of the file, not during process termination.
+ (Presently, an unload only happens in the context of re-loading
+ the file due to an explicit <command>LOAD</> command.)
</para>
</sect2>
@@ -1912,31 +1965,6 @@ concat_text(PG_FUNCTION_ARGS)
<listitem>
<para>
- To ensure your module is not loaded into an incompatible server,
- it must include a <quote>magic block</>. This allows
- the server to detect obvious incompatibilities, such as a module
- compiled for a different major version of
- <productname>PostgreSQL</productname>. A magic block is required
- as of <productname>PostgreSQL</productname> 8.2. To include a magic
- block, write this in one (and only one) of your module source files,
- after having included the header <filename>fmgr.h</>:
- </para>
-
-<programlisting>
-#ifdef PG_MODULE_MAGIC
-PG_MODULE_MAGIC;
-#endif
-</programlisting>
-
- <para>
- The <literal>#ifdef</> test can be omitted if your code doesn't
- need to compile against pre-8.2 <productname>PostgreSQL</productname>
- releases.
- </para>
- </listitem>
-
- <listitem>
- <para>
Compiling and linking your code so that it can be dynamically
loaded into <productname>PostgreSQL</productname> always
requires special flags. See <xref linkend="dfunc"> for a
@@ -1947,6 +1975,13 @@ PG_MODULE_MAGIC;
<listitem>
<para>
+ Remember to define a <quote>magic block</> for your shared library,
+ as described in <xref linkend="xfunc-c-dynload">.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
When allocating memory, use the
<productname>PostgreSQL</productname> functions
<function>palloc</function><indexterm><primary>palloc</></> and <function>pfree</function><indexterm><primary>pfree</></>
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index f596dd50dc..443141cf12 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -197,9 +197,6 @@ bool Db_user_namespace = false;
char *bonjour_name;
-/* list of library:init-function to be preloaded */
-char *preload_libraries_string = NULL;
-
/* PIDs of special child processes; 0 when not running */
static pid_t StartupPID = 0,
BgWriterPID = 0,
@@ -710,11 +707,9 @@ PostmasterMain(int argc, char *argv[])
#endif
/*
- * process any libraries that should be preloaded and optionally
- * pre-initialized
+ * process any libraries that should be preloaded at postmaster start
*/
- if (preload_libraries_string)
- process_preload_libraries(preload_libraries_string);
+ process_preload_libraries();
/*
* Remove old temporary files. At this point there can be no other
diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c
index 004ba2e327..da93f07b44 100644
--- a/src/backend/utils/fmgr/dfmgr.c
+++ b/src/backend/utils/fmgr/dfmgr.c
@@ -25,6 +25,10 @@
#include "utils/dynamic_loader.h"
+/* signatures for PostgreSQL-specific library init/fini functions */
+typedef void (*PG_init_t)(void);
+typedef void (*PG_fini_t)(void);
+
/*
* List of dynamically loaded files (kept in malloc'd memory).
*/
@@ -79,7 +83,7 @@ static const Pg_magic_struct magic_data = PG_MODULE_MAGIC_DATA;
* identifying the library file. The filehandle can be used with
* lookup_external_function to lookup additional functions in the same file
* at less cost than repeating load_external_function.
- */
+ */
PGFunction
load_external_function(char *filename, char *funcname,
bool signalNotFound, void **filehandle)
@@ -90,6 +94,7 @@ load_external_function(char *filename, char *funcname,
char *load_error;
struct stat stat_buf;
char *fullname;
+ PG_init_t PG_init;
fullname = expand_dynamic_library_name(filename);
if (!fullname)
@@ -201,7 +206,14 @@ load_external_function(char *filename, char *funcname,
fullname),
errhint("Extension libraries are now required to use the PG_MODULE_MAGIC macro.")));
}
-
+
+ /*
+ * If the library has a _PG_init() function, call it.
+ */
+ PG_init = (PG_init_t) pg_dlsym(file_scanner->handle, "_PG_init");
+ if (PG_init)
+ (*PG_init)();
+
/* OK to link it into list */
if (file_list == NULL)
file_list = file_scanner;
@@ -248,6 +260,7 @@ load_file(char *filename)
*nxt;
struct stat stat_buf;
char *fullname;
+ PG_fini_t PG_fini;
fullname = expand_dynamic_library_name(filename);
if (!fullname)
@@ -280,6 +293,14 @@ load_file(char *filename)
else
file_list = nxt;
clear_external_function_hash(file_scanner->handle);
+
+ /*
+ * If the library has a _PG_fini() function, call it.
+ */
+ PG_fini = (PG_fini_t) pg_dlsym(file_scanner->handle, "_PG_fini");
+ if (PG_fini)
+ (*PG_fini)();
+
pg_dlclose(file_scanner->handle);
free((char *) file_scanner);
/* prv does not change */
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 9c1c208a4e..5f06ed0812 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -1097,14 +1097,14 @@ ValidatePgVersion(const char *path)
*-------------------------------------------------------------------------
*/
-typedef void (*func_ptr) ();
+/* GUC variable: list of library names to be preloaded */
+char *preload_libraries_string = NULL;
/*
- * process any libraries that should be preloaded and
- * optionally pre-initialized
+ * process any libraries that should be preloaded at postmaster start
*/
void
-process_preload_libraries(char *preload_libraries_string)
+process_preload_libraries(void)
{
char *rawstring;
List *elemlist;
@@ -1131,54 +1131,14 @@ process_preload_libraries(char *preload_libraries_string)
foreach(l, elemlist)
{
char *tok = (char *) lfirst(l);
- char *sep = strstr(tok, ":");
- char *filename = NULL;
- char *funcname = NULL;
- func_ptr initfunc;
-
- if (sep)
- {
- /*
- * a colon separator implies there is an initialization function
- * that we need to run in addition to loading the library
- */
- size_t filename_len = sep - tok;
- size_t funcname_len = strlen(tok) - filename_len - 1;
-
- filename = (char *) palloc(filename_len + 1);
- memcpy(filename, tok, filename_len);
- filename[filename_len] = '\0';
-
- funcname = (char *) palloc(funcname_len + 1);
- strcpy(funcname, sep + 1);
- }
- else
- {
- /*
- * no separator -- just load the library
- */
- filename = pstrdup(tok);
- funcname = NULL;
- }
+ char *filename;
+ filename = pstrdup(tok);
canonicalize_path(filename);
- initfunc = (func_ptr) load_external_function(filename, funcname,
- true, NULL);
- if (initfunc)
- (*initfunc) ();
-
- if (funcname)
- ereport(LOG,
- (errmsg("preloaded library \"%s\" with initialization function \"%s\"",
- filename, funcname)));
- else
- ereport(LOG,
- (errmsg("preloaded library \"%s\"",
- filename)));
-
+ (void) load_external_function(filename, NULL, true, NULL);
+ ereport(LOG,
+ (errmsg("preloaded library \"%s\"", filename)));
pfree(filename);
- if (funcname)
- pfree(funcname);
}
pfree(rawstring);
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index bf6be45dbe..6674edb368 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -307,6 +307,8 @@ extern void BaseInit(void);
/* in utils/init/miscinit.c */
extern bool IgnoreSystemIndexes;
+extern char *preload_libraries_string;
+
extern void SetReindexProcessing(Oid heapOid, Oid indexOid);
extern void ResetReindexProcessing(void);
extern bool ReindexIsProcessingHeap(Oid heapOid);
@@ -317,6 +319,6 @@ extern void TouchSocketLockFile(void);
extern void RecordSharedMemoryInLockFile(unsigned long id1,
unsigned long id2);
extern void ValidatePgVersion(const char *path);
-extern void process_preload_libraries(char *preload_libraries_string);
+extern void process_preload_libraries(void);
#endif /* MISCADMIN_H */
diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h
index d7e3871892..4ca43d606e 100644
--- a/src/include/postmaster/postmaster.h
+++ b/src/include/postmaster/postmaster.h
@@ -25,7 +25,6 @@ extern char *ListenAddresses;
extern bool ClientAuthInProgress;
extern int PreAuthDelay;
extern int AuthenticationTimeout;
-extern char *preload_libraries_string;
extern bool Log_connections;
extern bool log_hostname;
extern char *bonjour_name;
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 473ddd3ed8..8a6083ec31 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -87,7 +87,6 @@ typedef struct plperl_query_desc
/**********************************************************************
* Global data
**********************************************************************/
-static bool plperl_firstcall = true;
static bool plperl_safe_init_done = false;
static PerlInterpreter *plperl_interp = NULL;
static HV *plperl_proc_hash = NULL;
@@ -101,12 +100,11 @@ static plperl_call_data *current_call_data = NULL;
/**********************************************************************
* Forward declarations
**********************************************************************/
-static void plperl_init_all(void);
-static void plperl_init_interp(void);
-
Datum plperl_call_handler(PG_FUNCTION_ARGS);
Datum plperl_validator(PG_FUNCTION_ARGS);
-void plperl_init(void);
+void _PG_init(void);
+
+static void plperl_init_interp(void);
static Datum plperl_func_handler(PG_FUNCTION_ARGS);
@@ -135,16 +133,21 @@ perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
}
-/* Perform initialization during postmaster startup. */
-
+/*
+ * _PG_init() - library load-time initialization
+ *
+ * DO NOT make this static nor change its name!
+ */
void
-plperl_init(void)
+_PG_init(void)
{
- if (!plperl_firstcall)
+ /* Be sure we do initialization only once (should be redundant now) */
+ static bool inited = false;
+
+ if (inited)
return;
- DefineCustomBoolVariable(
- "plperl.use_strict",
+ DefineCustomBoolVariable("plperl.use_strict",
"If true, will compile trusted and untrusted perl code in strict mode",
NULL,
&plperl_use_strict,
@@ -154,19 +157,8 @@ plperl_init(void)
EmitWarningsOnPlaceholders("plperl");
plperl_init_interp();
- plperl_firstcall = false;
-}
-
-
-/* Perform initialization during backend startup. */
-static void
-plperl_init_all(void)
-{
- if (plperl_firstcall)
- plperl_init();
-
- /* We don't need to do anything yet when a new backend starts. */
+ inited = true;
}
/* Each of these macros must represent a single string literal */
@@ -657,8 +649,6 @@ plperl_call_handler(PG_FUNCTION_ARGS)
Datum retval;
plperl_call_data *save_call_data;
- plperl_init_all();
-
save_call_data = current_call_data;
PG_TRY();
{
@@ -741,11 +731,7 @@ plperl_validator(PG_FUNCTION_ARGS)
/* Postpone body checks if !check_function_bodies */
if (check_function_bodies)
{
- plperl_proc_desc *prodesc;
-
- plperl_init_all();
-
- prodesc = compile_plperl_function(funcoid, istrigger);
+ (void) compile_plperl_function(funcoid, istrigger);
}
/* the result of a validator is ignored */
diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c
index 2da186f01b..4e095a0735 100644
--- a/src/pl/plpgsql/src/pl_handler.c
+++ b/src/pl/plpgsql/src/pl_handler.c
@@ -28,41 +28,25 @@ extern DLLIMPORT bool check_function_bodies;
PG_MODULE_MAGIC;
-static bool plpgsql_firstcall = true;
-
-static void plpgsql_init_all(void);
-
/*
- * plpgsql_init() - postmaster-startup safe initialization
+ * _PG_init() - library load-time initialization
*
- * DO NOT make this static --- it has to be callable by preload
+ * DO NOT make this static nor change its name!
*/
void
-plpgsql_init(void)
+_PG_init(void)
{
- /* Do initialization only once */
- if (!plpgsql_firstcall)
+ /* Be sure we do initialization only once (should be redundant now) */
+ static bool inited = false;
+
+ if (inited)
return;
plpgsql_HashTableInit();
RegisterXactCallback(plpgsql_xact_cb, NULL);
- plpgsql_firstcall = false;
-}
-
-/*
- * plpgsql_init_all() - Initialize all
- */
-static void
-plpgsql_init_all(void)
-{
- /* Execute any postmaster-startup safe initialization */
- plpgsql_init();
- /*
- * Any other initialization that must be done each time a new backend
- * starts -- currently none
- */
+ inited = true;
}
/* ----------
@@ -81,9 +65,6 @@ plpgsql_call_handler(PG_FUNCTION_ARGS)
Datum retval;
int rc;
- /* perform initialization */
- plpgsql_init_all();
-
/*
* Connect to SPI manager
*/
@@ -135,9 +116,6 @@ plpgsql_validator(PG_FUNCTION_ARGS)
bool istrigger = false;
int i;
- /* perform initialization */
- plpgsql_init_all();
-
/* Get the new function's pg_proc entry */
tuple = SearchSysCache(PROCOID,
ObjectIdGetDatum(funcoid),
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index 831b77f3dc..d9e144d25c 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -678,7 +678,7 @@ extern void plpgsql_compile_error_callback(void *arg);
* Functions in pl_handler.c
* ----------
*/
-extern void plpgsql_init(void);
+extern void _PG_init(void);
extern Datum plpgsql_call_handler(PG_FUNCTION_ARGS);
extern Datum plpgsql_validator(PG_FUNCTION_ARGS);
diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c
index 007566a73b..69a2e644a4 100644
--- a/src/pl/plpython/plpython.c
+++ b/src/pl/plpython/plpython.c
@@ -155,11 +155,11 @@ typedef struct PLyResultObject
/* function declarations */
/* Two exported functions: first is the magic telling Postgresql
- * what function call interface it implements. Second allows
- * preinitialization of the interpreter during postmaster startup.
+ * what function call interface it implements. Second is for
+ * initialization of the interpreter during library load.
*/
Datum plpython_call_handler(PG_FUNCTION_ARGS);
-void plpython_init(void);
+void _PG_init(void);
PG_FUNCTION_INFO_V1(plpython_call_handler);
@@ -169,7 +169,6 @@ PG_FUNCTION_INFO_V1(plpython_call_handler);
* of plpython_call_handler. initialize the python interpreter
* and global data.
*/
-static void PLy_init_all(void);
static void PLy_init_interp(void);
static void PLy_init_plpy(void);
@@ -233,9 +232,6 @@ static PyObject *PLyLong_FromString(const char *);
static PyObject *PLyString_FromString(const char *);
-/* global data */
-static bool PLy_first_call = true;
-
/*
* Currently active plpython function
*/
@@ -301,8 +297,6 @@ plpython_call_handler(PG_FUNCTION_ARGS)
PLyProcedure *save_curr_proc;
PLyProcedure *volatile proc = NULL;
- PLy_init_all();
-
if (SPI_connect() != SPI_OK_CONNECT)
elog(ERROR, "could not connect to SPI manager");
@@ -2263,25 +2257,19 @@ PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status)
*/
/*
- * plpython_init() - Initialize everything that can be
- * safely initialized during postmaster
- * startup.
+ * _PG_init() - library load-time initialization
*
- * DO NOT make this static --- it has to be callable by preload
+ * DO NOT make this static nor change its name!
*/
void
-plpython_init(void)
+_PG_init(void)
{
- static volatile bool init_active = false;
+ /* Be sure we do initialization only once (should be redundant now) */
+ static bool inited = false;
- /* Do initialization only once */
- if (!PLy_first_call)
+ if (inited)
return;
- if (init_active)
- elog(FATAL, "initialization of language module failed");
- init_active = true;
-
Py_Initialize();
PLy_init_interp();
PLy_init_plpy();
@@ -2291,20 +2279,7 @@ plpython_init(void)
if (PLy_procedure_cache == NULL)
PLy_elog(ERROR, "could not create procedure cache");
- PLy_first_call = false;
-}
-
-static void
-PLy_init_all(void)
-{
- /* Execute postmaster-startup safe initialization */
- if (PLy_first_call)
- plpython_init();
-
- /*
- * Any other initialization that must be done each time a new backend
- * starts -- currently none
- */
+ inited = true;
}
static void
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 4bdcd45283..d96591f51d 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -120,15 +120,14 @@ static pltcl_proc_desc *pltcl_current_prodesc = NULL;
/**********************************************************************
* Forward declarations
**********************************************************************/
+Datum pltcl_call_handler(PG_FUNCTION_ARGS);
+Datum pltclu_call_handler(PG_FUNCTION_ARGS);
+void _PG_init(void);
+
static void pltcl_init_all(void);
static void pltcl_init_interp(Tcl_Interp *interp);
-
static void pltcl_init_load_unknown(Tcl_Interp *interp);
-Datum pltcl_call_handler(PG_FUNCTION_ARGS);
-Datum pltclu_call_handler(PG_FUNCTION_ARGS);
-void pltcl_init(void);
-
static Datum pltcl_func_handler(PG_FUNCTION_ARGS);
static HeapTuple pltcl_trigger_handler(PG_FUNCTION_ARGS);
@@ -182,17 +181,15 @@ perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
fmgr_info_cxt(functionId, finfo, TopMemoryContext);
}
-/**********************************************************************
- * pltcl_init() - Initialize all that's safe to do in the postmaster
+/*
+ * _PG_init() - library load-time initialization
*
- * DO NOT make this static --- it has to be callable by preload
- **********************************************************************/
+ * DO NOT make this static nor change its name!
+ */
void
-pltcl_init(void)
+_PG_init(void)
{
- /************************************************************
- * Do initialization only once
- ************************************************************/
+ /* Be sure we do initialization only once (should be redundant now) */
if (pltcl_pm_init_done)
return;
@@ -236,20 +233,15 @@ pltcl_init(void)
/**********************************************************************
* pltcl_init_all() - Initialize all
+ *
+ * This does initialization that can't be done in the postmaster, and
+ * hence is not safe to do at library load time.
**********************************************************************/
static void
pltcl_init_all(void)
{
/************************************************************
- * Execute postmaster-startup safe initialization
- ************************************************************/
- if (!pltcl_pm_init_done)
- pltcl_init();
-
- /************************************************************
- * Any other initialization that must be done each time a new
- * backend starts:
- * - Try to load the unknown procedure from pltcl_modules
+ * Try to load the unknown procedure from pltcl_modules
************************************************************/
if (!pltcl_be_init_done)
{