mirror of
https://github.com/postgres/postgres.git
synced 2025-11-09 06:21:09 +03:00
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.
This commit is contained in:
@@ -37,7 +37,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.497 2006/07/29 03:02:55 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.498 2006/08/08 19:15:07 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
@@ -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
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.86 2006/06/07 22:24:44 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.87 2006/08/08 19:15:08 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -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 */
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.155 2006/07/14 14:52:25 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.156 2006/08/08 19:15:08 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user