From 62f43d2731e4aa782ebd6503266f596103538a48 Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@telsasoft.com>
Date: Wed, 2 Feb 2022 20:54:49 -0600
Subject: [PATCH v5 3/3] show the GUC source in errcontext

---
 src/backend/utils/fmgr/dfmgr.c | 13 ++++++++++---
 src/backend/utils/misc/guc.c   | 24 ++++++++++++++++++++++++
 src/include/utils/guc.h        |  1 +
 3 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c
index 081d75fd724..9ccb12637a0 100644
--- a/src/backend/utils/fmgr/dfmgr.c
+++ b/src/backend/utils/fmgr/dfmgr.c
@@ -34,6 +34,7 @@
 #include "lib/stringinfo.h"
 #include "miscadmin.h"
 #include "storage/shmem.h"
+#include "utils/guc_tables.h"
 #include "utils/hsearch.h"
 
 
@@ -213,11 +214,17 @@ internal_load_library(const char *libname, const char *gucname)
 		 * Check for same files - different paths (ie, symlink or link)
 		 */
 		if (stat(libname, &stat_buf) == -1)
+		{
+			char *errstr = strerror(errno);
+			int linenum;
+			char *sourcefile = gucname ? GetConfigSourceFile(gucname, &linenum) : NULL;
 			ereport(ERROR,
 					(errcode_for_file_access(),
 					 gucname ? errcontext("while loading shared libraries for setting \"%s\"", gucname) : 0,
-					 errmsg("could not access file \"%s\": %m",
-							libname)));
+					 sourcefile ? errcontext("from %s:%d", sourcefile, linenum) : 0,
+					 errmsg("could not access file \"%s\": %s",
+							libname, errstr)));
+		}
 
 		for (file_scanner = file_list;
 			 file_scanner != NULL &&
@@ -281,7 +288,7 @@ internal_load_library(const char *libname, const char *gucname)
 		}
 		else
 		{
-			/* try to close library */
+			/* try to close library */ // Not needed due to ERROR ? //
 			dlclose(file_scanner->handle);
 			free((char *) file_scanner);
 			/* complain */
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 4e38e73a277..4e6fae2bd8b 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -8577,6 +8577,30 @@ GetConfigOptionFlags(const char *name, bool missing_ok)
 	return record->flags;
 }
 
+/*
+ * Get the source file and line associated with the given option, if it was set
+ * by a file.
+ *
+ * If the option doesn't exist, throw an ereport and don't return.
+ */
+char *
+GetConfigSourceFile(const char *name, int *linenum)
+{
+	struct config_generic *record;
+
+	record = find_option(name, false, false, ERROR);
+
+	/* Should not happen */
+	if (record == NULL)
+		return NULL;
+
+	if (record->source != PGC_S_FILE)
+		return NULL;
+
+	*linenum = record->sourceline;
+	return record->sourcefile;
+}
+
 
 /*
  * flatten_set_variable_args
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index e734493a484..cdb5e3488c5 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -367,6 +367,7 @@ extern const char *GetConfigOption(const char *name, bool missing_ok,
 								   bool restrict_privileged);
 extern const char *GetConfigOptionResetString(const char *name);
 extern int	GetConfigOptionFlags(const char *name, bool missing_ok);
+extern char	*GetConfigSourceFile(const char *name, int *linenum);
 extern void ProcessConfigFile(GucContext context);
 extern char *convert_GUC_name_for_parameter_acl(const char *name);
 extern bool check_GUC_name_for_parameter_acl(const char *name);
-- 
2.17.1

