Skip to content

Commit b09bfca

Browse files
committed
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.
1 parent e00664d commit b09bfca

File tree

12 files changed

+178
-238
lines changed

12 files changed

+178
-238
lines changed

doc/src/sgml/config.sgml

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.72 2006/08/08 01:23:15 momjian Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.73 2006/08/08 19:15:07 tgl Exp $ -->
22

33
<chapter Id="runtime-config">
44
<title>Server Configuration</title>
@@ -957,38 +957,35 @@ SET ENABLE_SEQSCAN TO OFF;
957957
<listitem>
958958
<para>
959959
This variable specifies one or more shared libraries that are
960-
to be preloaded at server start. A parameterless
961-
initialization function can optionally be called for each
962-
library. To specify that, add a colon and the name of the
963-
initialization function after the library name. For example
964-
<literal>'$libdir/mylib:mylib_init'</literal> would cause
965-
<literal>mylib</> to be preloaded and <literal>mylib_init</>
966-
to be executed. If more than one library is to be loaded,
967-
separate their names with commas.
968-
</para>
969-
970-
<para>
971-
If a specified library or initialization function is not found,
972-
the server will fail to start.
960+
to be preloaded at server start. If more than one library is to be
961+
loaded, separate their names with commas. For example,
962+
<literal>'$libdir/mylib'</literal> would cause
963+
<literal>mylib.so</> (or on some platforms,
964+
<literal>mylib.sl</>) to be preloaded from the installation's
965+
standard library directory.
973966
</para>
974967

975968
<para>
976969
<productname>PostgreSQL</productname> procedural language
977970
libraries can be preloaded in this way, typically by using the
978-
syntax <literal>'$libdir/plXXX:plXXX_init'</literal> where
971+
syntax <literal>'$libdir/plXXX'</literal> where
979972
<literal>XXX</literal> is <literal>pgsql</>, <literal>perl</>,
980973
<literal>tcl</>, or <literal>python</>.
981974
</para>
982975

983976
<para>
984-
By preloading a shared library (and initializing it if
985-
applicable), the library startup time is avoided when the
986-
library is first used. However, the time to start each new
977+
By preloading a shared library, the library startup time is avoided
978+
when the library is first used. However, the time to start each new
987979
server process may increase slightly, even if that process never
988980
uses the library. So this parameter is recommended only for
989981
libraries that will be used in most sessions.
990982
</para>
991983

984+
<para>
985+
If a specified library is not found,
986+
the server will fail to start.
987+
</para>
988+
992989
<para>
993990
Every PostgreSQL-supported library has a <quote>magic
994991
block</> that is checked to guarantee compatibility.

doc/src/sgml/xfunc.sgml

Lines changed: 67 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.115 2006/05/31 20:58:09 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.116 2006/08/08 19:15:07 tgl Exp $ -->
22

33
<sect1 id="xfunc">
44
<title>User-Defined Functions</title>
@@ -1148,6 +1148,15 @@ CREATE FUNCTION square_root(double precision) RETURNS double precision
11481148
that fails as well, the load will fail.
11491149
</para>
11501150

1151+
<para>
1152+
It is recommended to locate shared libraries either relative to
1153+
<literal>$libdir</literal> or through the dynamic library path.
1154+
This simplifies version upgrades if the new installation is at a
1155+
different location. The actual directory that
1156+
<literal>$libdir</literal> stands for can be found out with the
1157+
command <literal>pg_config --pkglibdir</literal>.
1158+
</para>
1159+
11511160
<para>
11521161
The user ID the <productname>PostgreSQL</productname> server runs
11531162
as must be able to traverse the path to the file you intend to
@@ -1173,6 +1182,32 @@ CREATE FUNCTION square_root(double precision) RETURNS double precision
11731182
</para>
11741183
</note>
11751184

1185+
<indexterm zone="xfunc-c-dynload">
1186+
<primary>magic block</primary>
1187+
</indexterm>
1188+
1189+
<para>
1190+
To ensure that a dynamically loaded object file is not loaded into an
1191+
incompatible server, <productname>PostgreSQL</productname> checks that the
1192+
file contains a <quote>magic block</> with the appropriate contents.
1193+
This allows the server to detect obvious incompatibilities, such as code
1194+
compiled for a different major version of
1195+
<productname>PostgreSQL</productname>. A magic block is required as of
1196+
<productname>PostgreSQL</productname> 8.2. To include a magic block,
1197+
write this in one (and only one) of the module source files, after having
1198+
included the header <filename>fmgr.h</>:
1199+
1200+
<programlisting>
1201+
#ifdef PG_MODULE_MAGIC
1202+
PG_MODULE_MAGIC;
1203+
#endif
1204+
</programlisting>
1205+
1206+
The <literal>#ifdef</> test can be omitted if the code doesn't
1207+
need to compile against pre-8.2 <productname>PostgreSQL</productname>
1208+
releases.
1209+
</para>
1210+
11761211
<para>
11771212
After it is used for the first time, a dynamically loaded object
11781213
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
11831218
fresh session.
11841219
</para>
11851220

1221+
<indexterm zone="xfunc-c-dynload">
1222+
<primary>_PG_init</primary>
1223+
</indexterm>
1224+
<indexterm zone="xfunc-c-dynload">
1225+
<primary>_PG_fini</primary>
1226+
</indexterm>
1227+
<indexterm zone="xfunc-c-dynload">
1228+
<primary>library initialization function</primary>
1229+
</indexterm>
1230+
<indexterm zone="xfunc-c-dynload">
1231+
<primary>library finalization function</primary>
1232+
</indexterm>
1233+
11861234
<para>
1187-
It is recommended to locate shared libraries either relative to
1188-
<literal>$libdir</literal> or through the dynamic library path.
1189-
This simplifies version upgrades if the new installation is at a
1190-
different location. The actual directory that
1191-
<literal>$libdir</literal> stands for can be found out with the
1192-
command <literal>pg_config --pkglibdir</literal>.
1235+
Optionally, a dynamically loaded file can contain initialization and
1236+
finalization functions. If the file includes a function named
1237+
<literal>_PG_init</>, that function will be called immediately after
1238+
loading the file. The function receives no parameters and should
1239+
return void. If the file includes a function named
1240+
<literal>_PG_fini</>, that function will be called immediately before
1241+
unloading the file. Likewise, the function receives no parameters and
1242+
should return void. Note that <literal>_PG_fini</> will only be called
1243+
during an unload of the file, not during process termination.
1244+
(Presently, an unload only happens in the context of re-loading
1245+
the file due to an explicit <command>LOAD</> command.)
11931246
</para>
11941247

11951248
</sect2>
@@ -1910,31 +1963,6 @@ concat_text(PG_FUNCTION_ARGS)
19101963
</para>
19111964
</listitem>
19121965

1913-
<listitem>
1914-
<para>
1915-
To ensure your module is not loaded into an incompatible server,
1916-
it must include a <quote>magic block</>. This allows
1917-
the server to detect obvious incompatibilities, such as a module
1918-
compiled for a different major version of
1919-
<productname>PostgreSQL</productname>. A magic block is required
1920-
as of <productname>PostgreSQL</productname> 8.2. To include a magic
1921-
block, write this in one (and only one) of your module source files,
1922-
after having included the header <filename>fmgr.h</>:
1923-
</para>
1924-
1925-
<programlisting>
1926-
#ifdef PG_MODULE_MAGIC
1927-
PG_MODULE_MAGIC;
1928-
#endif
1929-
</programlisting>
1930-
1931-
<para>
1932-
The <literal>#ifdef</> test can be omitted if your code doesn't
1933-
need to compile against pre-8.2 <productname>PostgreSQL</productname>
1934-
releases.
1935-
</para>
1936-
</listitem>
1937-
19381966
<listitem>
19391967
<para>
19401968
Compiling and linking your code so that it can be dynamically
@@ -1945,6 +1973,13 @@ PG_MODULE_MAGIC;
19451973
</para>
19461974
</listitem>
19471975

1976+
<listitem>
1977+
<para>
1978+
Remember to define a <quote>magic block</> for your shared library,
1979+
as described in <xref linkend="xfunc-c-dynload">.
1980+
</para>
1981+
</listitem>
1982+
19481983
<listitem>
19491984
<para>
19501985
When allocating memory, use the

src/backend/postmaster/postmaster.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
*
3838
*
3939
* IDENTIFICATION
40-
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.497 2006/07/29 03:02:55 tgl Exp $
40+
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.498 2006/08/08 19:15:07 tgl Exp $
4141
*
4242
* NOTES
4343
*
@@ -197,9 +197,6 @@ bool Db_user_namespace = false;
197197

198198
char *bonjour_name;
199199

200-
/* list of library:init-function to be preloaded */
201-
char *preload_libraries_string = NULL;
202-
203200
/* PIDs of special child processes; 0 when not running */
204201
static pid_t StartupPID = 0,
205202
BgWriterPID = 0,
@@ -710,11 +707,9 @@ PostmasterMain(int argc, char *argv[])
710707
#endif
711708

712709
/*
713-
* process any libraries that should be preloaded and optionally
714-
* pre-initialized
710+
* process any libraries that should be preloaded at postmaster start
715711
*/
716-
if (preload_libraries_string)
717-
process_preload_libraries(preload_libraries_string);
712+
process_preload_libraries();
718713

719714
/*
720715
* Remove old temporary files. At this point there can be no other

src/backend/utils/fmgr/dfmgr.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.86 2006/06/07 22:24:44 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.87 2006/08/08 19:15:08 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -25,6 +25,10 @@
2525
#include "utils/dynamic_loader.h"
2626

2727

28+
/* signatures for PostgreSQL-specific library init/fini functions */
29+
typedef void (*PG_init_t)(void);
30+
typedef void (*PG_fini_t)(void);
31+
2832
/*
2933
* List of dynamically loaded files (kept in malloc'd memory).
3034
*/
@@ -79,7 +83,7 @@ static const Pg_magic_struct magic_data = PG_MODULE_MAGIC_DATA;
7983
* identifying the library file. The filehandle can be used with
8084
* lookup_external_function to lookup additional functions in the same file
8185
* at less cost than repeating load_external_function.
82-
*/
86+
*/
8387
PGFunction
8488
load_external_function(char *filename, char *funcname,
8589
bool signalNotFound, void **filehandle)
@@ -90,6 +94,7 @@ load_external_function(char *filename, char *funcname,
9094
char *load_error;
9195
struct stat stat_buf;
9296
char *fullname;
97+
PG_init_t PG_init;
9398

9499
fullname = expand_dynamic_library_name(filename);
95100
if (!fullname)
@@ -201,7 +206,14 @@ load_external_function(char *filename, char *funcname,
201206
fullname),
202207
errhint("Extension libraries are now required to use the PG_MODULE_MAGIC macro.")));
203208
}
204-
209+
210+
/*
211+
* If the library has a _PG_init() function, call it.
212+
*/
213+
PG_init = (PG_init_t) pg_dlsym(file_scanner->handle, "_PG_init");
214+
if (PG_init)
215+
(*PG_init)();
216+
205217
/* OK to link it into list */
206218
if (file_list == NULL)
207219
file_list = file_scanner;
@@ -248,6 +260,7 @@ load_file(char *filename)
248260
*nxt;
249261
struct stat stat_buf;
250262
char *fullname;
263+
PG_fini_t PG_fini;
251264

252265
fullname = expand_dynamic_library_name(filename);
253266
if (!fullname)
@@ -280,6 +293,14 @@ load_file(char *filename)
280293
else
281294
file_list = nxt;
282295
clear_external_function_hash(file_scanner->handle);
296+
297+
/*
298+
* If the library has a _PG_fini() function, call it.
299+
*/
300+
PG_fini = (PG_fini_t) pg_dlsym(file_scanner->handle, "_PG_fini");
301+
if (PG_fini)
302+
(*PG_fini)();
303+
283304
pg_dlclose(file_scanner->handle);
284305
free((char *) file_scanner);
285306
/* prv does not change */

src/backend/utils/init/miscinit.c

Lines changed: 10 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.155 2006/07/14 14:52:25 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.156 2006/08/08 19:15:08 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1097,14 +1097,14 @@ ValidatePgVersion(const char *path)
10971097
*-------------------------------------------------------------------------
10981098
*/
10991099

1100-
typedef void (*func_ptr) ();
1100+
/* GUC variable: list of library names to be preloaded */
1101+
char *preload_libraries_string = NULL;
11011102

11021103
/*
1103-
* process any libraries that should be preloaded and
1104-
* optionally pre-initialized
1104+
* process any libraries that should be preloaded at postmaster start
11051105
*/
11061106
void
1107-
process_preload_libraries(char *preload_libraries_string)
1107+
process_preload_libraries(void)
11081108
{
11091109
char *rawstring;
11101110
List *elemlist;
@@ -1131,54 +1131,14 @@ process_preload_libraries(char *preload_libraries_string)
11311131
foreach(l, elemlist)
11321132
{
11331133
char *tok = (char *) lfirst(l);
1134-
char *sep = strstr(tok, ":");
1135-
char *filename = NULL;
1136-
char *funcname = NULL;
1137-
func_ptr initfunc;
1138-
1139-
if (sep)
1140-
{
1141-
/*
1142-
* a colon separator implies there is an initialization function
1143-
* that we need to run in addition to loading the library
1144-
*/
1145-
size_t filename_len = sep - tok;
1146-
size_t funcname_len = strlen(tok) - filename_len - 1;
1147-
1148-
filename = (char *) palloc(filename_len + 1);
1149-
memcpy(filename, tok, filename_len);
1150-
filename[filename_len] = '\0';
1151-
1152-
funcname = (char *) palloc(funcname_len + 1);
1153-
strcpy(funcname, sep + 1);
1154-
}
1155-
else
1156-
{
1157-
/*
1158-
* no separator -- just load the library
1159-
*/
1160-
filename = pstrdup(tok);
1161-
funcname = NULL;
1162-
}
1134+
char *filename;
11631135

1136+
filename = pstrdup(tok);
11641137
canonicalize_path(filename);
1165-
initfunc = (func_ptr) load_external_function(filename, funcname,
1166-
true, NULL);
1167-
if (initfunc)
1168-
(*initfunc) ();
1169-
1170-
if (funcname)
1171-
ereport(LOG,
1172-
(errmsg("preloaded library \"%s\" with initialization function \"%s\"",
1173-
filename, funcname)));
1174-
else
1175-
ereport(LOG,
1176-
(errmsg("preloaded library \"%s\"",
1177-
filename)));
1178-
1138+
(void) load_external_function(filename, NULL, true, NULL);
1139+
ereport(LOG,
1140+
(errmsg("preloaded library \"%s\"", filename)));
11791141
pfree(filename);
1180-
if (funcname)
1181-
pfree(funcname);
11821142
}
11831143

11841144
pfree(rawstring);

0 commit comments

Comments
 (0)