mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03: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:
1
src/backend/port/.gitignore
vendored
1
src/backend/port/.gitignore
vendored
@ -1,4 +1,3 @@
|
||||
/dynloader.c
|
||||
/pg_sema.c
|
||||
/pg_shmem.c
|
||||
/tas.s
|
||||
|
@ -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
|
||||
|
@ -1,7 +0,0 @@
|
||||
/*
|
||||
* src/backend/port/dynloader/aix.c
|
||||
*
|
||||
* Dummy file used for nothing at this point
|
||||
*
|
||||
* see aix.h
|
||||
*/
|
@ -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 */
|
@ -1,3 +0,0 @@
|
||||
/* src/backend/port/dynloader/cygwin.c */
|
||||
|
||||
/* Dummy file used for nothing at this point; see cygwin.h */
|
@ -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 */
|
@ -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();
|
||||
}
|
@ -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);
|
@ -1,7 +0,0 @@
|
||||
/*
|
||||
* src/backend/port/dynloader/freebsd.c
|
||||
*
|
||||
* Dummy file used for nothing at this point
|
||||
*
|
||||
* see freebsd.h
|
||||
*/
|
@ -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 */
|
@ -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;
|
||||
}
|
@ -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);
|
@ -1,7 +0,0 @@
|
||||
/*
|
||||
* src/backend/port/dynloader/linux.c
|
||||
*
|
||||
* Dummy file used for nothing at this point
|
||||
*
|
||||
* see linux.h
|
||||
*/
|
@ -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 */
|
@ -1,7 +0,0 @@
|
||||
/*
|
||||
* src/backend/port/dynloader/netbsd.c
|
||||
*
|
||||
* Dummy file used for nothing at this point
|
||||
*
|
||||
* see netbsd.h
|
||||
*/
|
@ -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 */
|
@ -1,7 +0,0 @@
|
||||
/*
|
||||
* src/backend/port/dynloader/openbsd.c
|
||||
*
|
||||
* Dummy file used for nothing at this point
|
||||
*
|
||||
* see openbsd.h
|
||||
*/
|
@ -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 */
|
@ -1,7 +0,0 @@
|
||||
/*
|
||||
* src/backend/port/dynloader/solaris.c
|
||||
*
|
||||
* Dummy file used for nothing at this point
|
||||
*
|
||||
* see solaris.h
|
||||
*/
|
@ -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 */
|
@ -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;
|
||||
}
|
@ -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 */
|
Reference in New Issue
Block a user