From f617409943eb0c24051a4d480207805f0db31171 Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Thu, 13 Sep 2018 16:01:54 +1200 Subject: [PATCH 3/3] Log a WARNING if _PG_init() accesses syscache. Libraries that access syscache from _PG_init() don't work when loaded via shared_preload_libraries. Log a warning to indicate that it will not be allowed in a future release. Discussion: https://postgr.es/m/153512195228.1489.8545997741965926448%40wrigleys.postgresql.org --- src/backend/utils/cache/catcache.c | 10 ++++++++++ src/backend/utils/fmgr/dfmgr.c | 22 +++++++++++++++++++++- src/include/fmgr.h | 1 + 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index 5ddbf6eab1..59f2ddd48f 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -24,6 +24,7 @@ #include "access/xact.h" #include "catalog/pg_operator.h" #include "catalog/pg_type.h" +#include "fmgr.h" #include "miscadmin.h" #ifdef CATCACHE_STATS #include "storage/ipc.h" /* for on_proc_exit */ @@ -1227,6 +1228,15 @@ SearchCatCacheInternal(CatCache *cache, dlist_head *bucket; CatCTup *ct; + /* + * Libraries' _PG_init() functions should not access syscache. While that + * works in a regular backend, it results in extensions that cannot be + * loaded via shared_preload_libraries. + */ + if (unlikely(InitializingLibrary)) + ereport(WARNING, + (errmsg("syscache access from _PG_init() is deprecated and will not be allowed in a future release of PostgreSQL"))); + /* Make sure we're in an xact, even if this ends up being a cache hit */ Assert(IsTransactionState()); diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c index 4a5cc7cfc7..e7e946f899 100644 --- a/src/backend/utils/fmgr/dfmgr.c +++ b/src/backend/utils/fmgr/dfmgr.c @@ -76,6 +76,8 @@ static DynamicFileList *file_tail = NULL; char *Dynamic_library_path; +bool InitializingLibrary; + static void *internal_load_library(const char *libname); static void incompatible_module_error(const char *libname, const Pg_magic_struct *module_magic_data) pg_attribute_noreturn(); @@ -291,7 +293,25 @@ internal_load_library(const char *libname) */ PG_init = (PG_init_t) dlsym(file_scanner->handle, "_PG_init"); if (PG_init) - (*PG_init) (); + { + /* + * To prevent _PG_init() functions from doing certain things, + * we set a global flag while running the function. For now this + * just triggers a warning on syscache access. + */ + InitializingLibrary = true; + PG_TRY(); + { + (*PG_init) (); + } + PG_CATCH(); + { + InitializingLibrary = false; + PG_RE_THROW(); + } + PG_END_TRY(); + InitializingLibrary = false; + } /* OK to link it into list */ if (file_list == NULL) diff --git a/src/include/fmgr.h b/src/include/fmgr.h index 101f513ba6..888e31ef04 100644 --- a/src/include/fmgr.h +++ b/src/include/fmgr.h @@ -678,6 +678,7 @@ extern bool CheckFunctionValidatorAccess(Oid validatorOid, Oid functionOid); * Routines in dfmgr.c */ extern char *Dynamic_library_path; +extern bool InitializingLibrary; extern PGFunction load_external_function(const char *filename, const char *funcname, bool signalNotFound, void **filehandle); -- 2.17.0