1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-01 21:31:19 +03:00

Refactor dlopen() support

Nowadays, all platforms except Windows and older HP-UX have standard
dlopen() support.  So having a separate implementation per platform
under src/backend/port/dynloader/ is a bit excessive.  Instead, treat
dlopen() like other library functions that happen to be missing
sometimes and put a replacement implementation under src/port/.

Discussion: https://www.postgresql.org/message-id/flat/e11a49cb-570a-60b7-707d-7084c8de0e61%402ndquadrant.com#54e735ae37476a121abb4e33c2549b03
This commit is contained in:
Peter Eisentraut
2018-09-06 10:07:24 +02:00
parent ac27c74def
commit 842cb9fa62
37 changed files with 172 additions and 540 deletions

View File

@@ -293,7 +293,7 @@ ifeq ($(PORTNAME), win32)
endif
distclean: clean
rm -f port/tas.s port/dynloader.c port/pg_sema.c port/pg_shmem.c
rm -f port/tas.s port/pg_sema.c port/pg_shmem.c
maintainer-clean: distclean
$(MAKE) -C catalog $@

View File

@@ -1,4 +1,3 @@
/dynloader.c
/pg_sema.c
/pg_shmem.c
/tas.s

View File

@@ -21,7 +21,7 @@ subdir = src/backend/port
top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
OBJS = atomics.o dynloader.o pg_sema.o pg_shmem.o $(TAS)
OBJS = atomics.o pg_sema.o pg_shmem.o $(TAS)
ifeq ($(PORTNAME), win32)
SUBDIRS += win32

View File

@@ -1,7 +0,0 @@
/*
* src/backend/port/dynloader/aix.c
*
* Dummy file used for nothing at this point
*
* see aix.h
*/

View File

@@ -1,39 +0,0 @@
/*-------------------------------------------------------------------------
*
* aix.h
* prototypes for AIX-specific routines
*
*
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/port/dynloader/aix.h
*
*-------------------------------------------------------------------------
*/
#ifndef PORT_PROTOS_H
#define PORT_PROTOS_H
#include <dlfcn.h>
#include "utils/dynamic_loader.h" /* pgrminclude ignore */
/*
* In some older systems, the RTLD_NOW flag isn't defined and the mode
* argument to dlopen must always be 1. The RTLD_GLOBAL flag is wanted
* if available, but it doesn't exist everywhere.
* If it doesn't exist, set it to 0 so it has no effect.
*/
#ifndef RTLD_NOW
#define RTLD_NOW 1
#endif
#ifndef RTLD_GLOBAL
#define RTLD_GLOBAL 0
#endif
#define pg_dlopen(f) dlopen((f), RTLD_NOW | RTLD_GLOBAL)
#define pg_dlsym(h, f) ((PGFunction) dlsym(h, f))
#define pg_dlclose(h) dlclose(h)
#define pg_dlerror() dlerror()
#endif /* PORT_PROTOS_H */

View File

@@ -1,3 +0,0 @@
/* src/backend/port/dynloader/cygwin.c */
/* Dummy file used for nothing at this point; see cygwin.h */

View File

@@ -1,36 +0,0 @@
/*-------------------------------------------------------------------------
*
* Dynamic loader declarations for Cygwin
*
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/port/dynloader/cygwin.h
*
*-------------------------------------------------------------------------
*/
#ifndef PORT_PROTOS_H
#define PORT_PROTOS_H
#include <dlfcn.h>
#include "utils/dynamic_loader.h" /* pgrminclude ignore */
/*
* In some older systems, the RTLD_NOW flag isn't defined and the mode
* argument to dlopen must always be 1. The RTLD_GLOBAL flag is wanted
* if available, but it doesn't exist everywhere.
* If it doesn't exist, set it to 0 so it has no effect.
*/
#ifndef RTLD_NOW
#define RTLD_NOW 1
#endif
#ifndef RTLD_GLOBAL
#define RTLD_GLOBAL 0
#endif
#define pg_dlopen(f) dlopen((f), RTLD_NOW | RTLD_GLOBAL)
#define pg_dlsym dlsym
#define pg_dlclose dlclose
#define pg_dlerror dlerror
#endif /* PORT_PROTOS_H */

View File

@@ -1,35 +0,0 @@
/*
* Dynamic loading support for macOS (Darwin)
*
* src/backend/port/dynloader/darwin.c
*/
#include "postgres.h"
#include <dlfcn.h>
#include "dynloader.h"
void *
pg_dlopen(const char *filename)
{
return dlopen(filename, RTLD_NOW | RTLD_GLOBAL);
}
void
pg_dlclose(void *handle)
{
dlclose(handle);
}
PGFunction
pg_dlsym(void *handle, const char *funcname)
{
return dlsym(handle, funcname);
}
char *
pg_dlerror(void)
{
return dlerror();
}

View File

@@ -1,8 +0,0 @@
/* src/backend/port/dynloader/darwin.h */
#include "fmgr.h"
void *pg_dlopen(const char *filename);
PGFunction pg_dlsym(void *handle, const char *funcname);
void pg_dlclose(void *handle);
char *pg_dlerror(void);

View File

@@ -1,7 +0,0 @@
/*
* src/backend/port/dynloader/freebsd.c
*
* Dummy file used for nothing at this point
*
* see freebsd.h
*/

View File

@@ -1,38 +0,0 @@
/*-------------------------------------------------------------------------
*
* freebsd.h
* port-specific prototypes for FreeBSD
*
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/port/dynloader/freebsd.h
*
*-------------------------------------------------------------------------
*/
#ifndef PORT_PROTOS_H
#define PORT_PROTOS_H
#include <dlfcn.h>
#include "utils/dynamic_loader.h" /* pgrminclude ignore */
/*
* In some older systems, the RTLD_NOW flag isn't defined and the mode
* argument to dlopen must always be 1. The RTLD_GLOBAL flag is wanted
* if available, but it doesn't exist everywhere.
* If it doesn't exist, set it to 0 so it has no effect.
*/
#ifndef RTLD_NOW
#define RTLD_NOW 1
#endif
#ifndef RTLD_GLOBAL
#define RTLD_GLOBAL 0
#endif
#define pg_dlopen(f) dlopen((f), RTLD_NOW | RTLD_GLOBAL)
#define pg_dlsym dlsym
#define pg_dlclose dlclose
#define pg_dlerror dlerror
#endif /* PORT_PROTOS_H */

View File

@@ -1,68 +0,0 @@
/*-------------------------------------------------------------------------
*
* dynloader.c
* dynamic loader for HP-UX using the shared library mechanism
*
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* src/backend/port/dynloader/hpux.c
*
* NOTES
* all functions are defined here -- it's impossible to trace the
* shl_* routines from the bundled HP-UX debugger.
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
/* System includes */
#include <a.out.h>
#include <dl.h>
#include "dynloader.h"
#include "utils/dynamic_loader.h"
void *
pg_dlopen(const char *filename)
{
/*
* Use BIND_IMMEDIATE so that undefined symbols cause a failure return
* from shl_load(), rather than an abort() later on when we attempt to
* call the library!
*/
shl_t handle = shl_load(filename,
BIND_IMMEDIATE | BIND_VERBOSE | DYNAMIC_PATH,
0L);
return (void *) handle;
}
PGFunction
pg_dlsym(void *handle, const char *funcname)
{
PGFunction f;
if (shl_findsym((shl_t *) & handle, funcname, TYPE_PROCEDURE, &f) == -1)
f = (PGFunction) NULL;
return f;
}
void
pg_dlclose(void *handle)
{
shl_unload((shl_t) handle);
}
char *
pg_dlerror(void)
{
static char errmsg[] = "shl_load failed";
if (errno)
return strerror(errno);
return errmsg;
}

View File

@@ -1,25 +0,0 @@
/*-------------------------------------------------------------------------
*
* dynloader.h
* dynamic loader for HP-UX using the shared library mechanism
*
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* src/backend/port/dynloader/hpux.h
*
* NOTES
* all functions are defined here -- it's impossible to trace the
* shl_* routines from the bundled HP-UX debugger.
*
*-------------------------------------------------------------------------
*/
/* System includes */
#include "fmgr.h"
extern void *pg_dlopen(const char *filename);
extern PGFunction pg_dlsym(void *handle, const char *funcname);
extern void pg_dlclose(void *handle);
extern char *pg_dlerror(void);

View File

@@ -1,7 +0,0 @@
/*
* src/backend/port/dynloader/linux.c
*
* Dummy file used for nothing at this point
*
* see linux.h
*/

View File

@@ -1,38 +0,0 @@
/*-------------------------------------------------------------------------
*
* linux.h
* Port-specific prototypes for Linux
*
*
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/port/dynloader/linux.h
*
*-------------------------------------------------------------------------
*/
#ifndef PORT_PROTOS_H
#define PORT_PROTOS_H
#include "utils/dynamic_loader.h" /* pgrminclude ignore */
#include <dlfcn.h>
/*
* In some older systems, the RTLD_NOW flag isn't defined and the mode
* argument to dlopen must always be 1. The RTLD_GLOBAL flag is wanted
* if available, but it doesn't exist everywhere.
* If it doesn't exist, set it to 0 so it has no effect.
*/
#ifndef RTLD_NOW
#define RTLD_NOW 1
#endif
#ifndef RTLD_GLOBAL
#define RTLD_GLOBAL 0
#endif
#define pg_dlopen(f) dlopen((f), RTLD_NOW | RTLD_GLOBAL)
#define pg_dlsym dlsym
#define pg_dlclose dlclose
#define pg_dlerror dlerror
#endif /* PORT_PROTOS_H */

View File

@@ -1,7 +0,0 @@
/*
* src/backend/port/dynloader/netbsd.c
*
* Dummy file used for nothing at this point
*
* see netbsd.h
*/

View File

@@ -1,38 +0,0 @@
/*-------------------------------------------------------------------------
*
* netbsd.h
* port-specific prototypes for NetBSD
*
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/port/dynloader/netbsd.h
*
*-------------------------------------------------------------------------
*/
#ifndef PORT_PROTOS_H
#define PORT_PROTOS_H
#include <dlfcn.h>
#include "utils/dynamic_loader.h" /* pgrminclude ignore */
/*
* In some older systems, the RTLD_NOW flag isn't defined and the mode
* argument to dlopen must always be 1. The RTLD_GLOBAL flag is wanted
* if available, but it doesn't exist everywhere.
* If it doesn't exist, set it to 0 so it has no effect.
*/
#ifndef RTLD_NOW
#define RTLD_NOW 1
#endif
#ifndef RTLD_GLOBAL
#define RTLD_GLOBAL 0
#endif
#define pg_dlopen(f) dlopen((f), RTLD_NOW | RTLD_GLOBAL)
#define pg_dlsym dlsym
#define pg_dlclose dlclose
#define pg_dlerror dlerror
#endif /* PORT_PROTOS_H */

View File

@@ -1,7 +0,0 @@
/*
* src/backend/port/dynloader/openbsd.c
*
* Dummy file used for nothing at this point
*
* see openbsd.h
*/

View File

@@ -1,38 +0,0 @@
/*-------------------------------------------------------------------------
*
* openbsd.h
* port-specific prototypes for OpenBSD
*
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/port/dynloader/openbsd.h
*
*-------------------------------------------------------------------------
*/
#ifndef PORT_PROTOS_H
#define PORT_PROTOS_H
#include <dlfcn.h>
#include "utils/dynamic_loader.h" /* pgrminclude ignore */
/*
* In some older systems, the RTLD_NOW flag isn't defined and the mode
* argument to dlopen must always be 1. The RTLD_GLOBAL flag is wanted
* if available, but it doesn't exist everywhere.
* If it doesn't exist, set it to 0 so it has no effect.
*/
#ifndef RTLD_NOW
#define RTLD_NOW 1
#endif
#ifndef RTLD_GLOBAL
#define RTLD_GLOBAL 0
#endif
#define pg_dlopen(f) dlopen((f), RTLD_NOW | RTLD_GLOBAL)
#define pg_dlsym dlsym
#define pg_dlclose dlclose
#define pg_dlerror dlerror
#endif /* PORT_PROTOS_H */

View File

@@ -1,7 +0,0 @@
/*
* src/backend/port/dynloader/solaris.c
*
* Dummy file used for nothing at this point
*
* see solaris.h
*/

View File

@@ -1,38 +0,0 @@
/*-------------------------------------------------------------------------
*
* solaris.h
* port-specific prototypes for Solaris
*
*
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/backend/port/dynloader/solaris.h
*
*-------------------------------------------------------------------------
*/
#ifndef PORT_PROTOS_H
#define PORT_PROTOS_H
#include <dlfcn.h>
#include "utils/dynamic_loader.h" /* pgrminclude ignore */
/*
* In some older systems, the RTLD_NOW flag isn't defined and the mode
* argument to dlopen must always be 1. The RTLD_GLOBAL flag is wanted
* if available, but it doesn't exist everywhere.
* If it doesn't exist, set it to 0 so it has no effect.
*/
#ifndef RTLD_NOW
#define RTLD_NOW 1
#endif
#ifndef RTLD_GLOBAL
#define RTLD_GLOBAL 0
#endif
#define pg_dlopen(f) dlopen((f), RTLD_NOW | RTLD_GLOBAL)
#define pg_dlsym dlsym
#define pg_dlclose dlclose
#define pg_dlerror dlerror
#endif /* PORT_PROTOS_H */

View File

@@ -1,85 +0,0 @@
/* src/backend/port/dynloader/win32.c */
#include "postgres.h"
char *dlerror(void);
int dlclose(void *handle);
void *dlsym(void *handle, const char *symbol);
void *dlopen(const char *path, int mode);
static char last_dyn_error[512];
static void
set_dl_error(void)
{
DWORD err = GetLastError();
if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
err,
MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
last_dyn_error,
sizeof(last_dyn_error) - 1,
NULL) == 0)
{
snprintf(last_dyn_error, sizeof(last_dyn_error) - 1,
"unknown error %lu", err);
}
}
char *
dlerror(void)
{
if (last_dyn_error[0])
return last_dyn_error;
else
return NULL;
}
int
dlclose(void *handle)
{
if (!FreeLibrary((HMODULE) handle))
{
set_dl_error();
return 1;
}
last_dyn_error[0] = 0;
return 0;
}
void *
dlsym(void *handle, const char *symbol)
{
void *ptr;
ptr = GetProcAddress((HMODULE) handle, symbol);
if (!ptr)
{
set_dl_error();
return NULL;
}
last_dyn_error[0] = 0;
return ptr;
}
void *
dlopen(const char *path, int mode)
{
HMODULE h;
int prevmode;
/* Disable popup error messages when loading DLLs */
prevmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
h = LoadLibrary(path);
SetErrorMode(prevmode);
if (!h)
{
set_dl_error();
return NULL;
}
last_dyn_error[0] = 0;
return (void *) h;
}

View File

@@ -1,19 +0,0 @@
/*
* src/backend/port/dynloader/win32.h
*/
#ifndef PORT_PROTOS_H
#define PORT_PROTOS_H
#include "utils/dynamic_loader.h" /* pgrminclude ignore */
#define pg_dlopen(f) dlopen((f), 1)
#define pg_dlsym dlsym
#define pg_dlclose dlclose
#define pg_dlerror dlerror
char *dlerror(void);
int dlclose(void *handle);
void *dlsym(void *handle, const char *symbol);
void *dlopen(const char *path, int mode);
#endif /* PORT_PROTOS_H */

View File

@@ -124,7 +124,6 @@
#include "tcop/tcopprot.h"
#include "utils/builtins.h"
#include "utils/datetime.h"
#include "utils/dynamic_loader.h"
#include "utils/memutils.h"
#include "utils/pidfile.h"
#include "utils/ps_status.h"

View File

@@ -16,11 +16,14 @@
#include <sys/stat.h>
#include "dynloader.h"
#ifdef HAVE_DLOPEN
#include <dlfcn.h>
#endif
#include "fmgr.h"
#include "lib/stringinfo.h"
#include "miscadmin.h"
#include "storage/shmem.h"
#include "utils/dynamic_loader.h"
#include "utils/hsearch.h"
@@ -113,7 +116,7 @@ load_external_function(const char *filename, const char *funcname,
* should declare its second argument as "const char *", but older
* platforms might not, so for the time being we just cast away const.
*/
retval = (PGFunction) pg_dlsym(lib_handle, (char *) funcname);
retval = (PGFunction) dlsym(lib_handle, (char *) funcname);
if (retval == NULL && signalNotFound)
ereport(ERROR,
@@ -162,7 +165,7 @@ PGFunction
lookup_external_function(void *filehandle, const char *funcname)
{
/* as above, cast away const for the time being */
return (PGFunction) pg_dlsym(filehandle, (char *) funcname);
return (PGFunction) dlsym(filehandle, (char *) funcname);
}
@@ -228,10 +231,10 @@ internal_load_library(const char *libname)
#endif
file_scanner->next = NULL;
file_scanner->handle = pg_dlopen(file_scanner->filename);
file_scanner->handle = dlopen(file_scanner->filename, RTLD_NOW | RTLD_GLOBAL);
if (file_scanner->handle == NULL)
{
load_error = (char *) pg_dlerror();
load_error = dlerror();
free((char *) file_scanner);
/* errcode_for_file_access might not be appropriate here? */
ereport(ERROR,
@@ -242,7 +245,7 @@ internal_load_library(const char *libname)
/* Check the magic function to determine compatibility */
magic_func = (PGModuleMagicFunction)
pg_dlsym(file_scanner->handle, PG_MAGIC_FUNCTION_NAME_STRING);
dlsym(file_scanner->handle, PG_MAGIC_FUNCTION_NAME_STRING);
if (magic_func)
{
const Pg_magic_struct *magic_data_ptr = (*magic_func) ();
@@ -253,8 +256,8 @@ internal_load_library(const char *libname)
/* copy data block before unlinking library */
Pg_magic_struct module_magic_data = *magic_data_ptr;
/* try to unlink library */
pg_dlclose(file_scanner->handle);
/* try to close library */
dlclose(file_scanner->handle);
free((char *) file_scanner);
/* issue suitable complaint */
@@ -263,8 +266,8 @@ internal_load_library(const char *libname)
}
else
{
/* try to unlink library */
pg_dlclose(file_scanner->handle);
/* try to close library */
dlclose(file_scanner->handle);
free((char *) file_scanner);
/* complain */
ereport(ERROR,
@@ -276,7 +279,7 @@ internal_load_library(const char *libname)
/*
* If the library has a _PG_init() function, call it.
*/
PG_init = (PG_init_t) pg_dlsym(file_scanner->handle, "_PG_init");
PG_init = (PG_init_t) dlsym(file_scanner->handle, "_PG_init");
if (PG_init)
(*PG_init) ();
@@ -436,12 +439,12 @@ internal_unload_library(const char *libname)
/*
* If the library has a _PG_fini() function, call it.
*/
PG_fini = (PG_fini_t) pg_dlsym(file_scanner->handle, "_PG_fini");
PG_fini = (PG_fini_t) dlsym(file_scanner->handle, "_PG_fini");
if (PG_fini)
(*PG_fini) ();
clear_external_function_hash(file_scanner->handle);
pg_dlclose(file_scanner->handle);
dlclose(file_scanner->handle);
free((char *) file_scanner);
/* prv does not change */
}