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

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

diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c
index fcda19b7973..b679de0455e 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 c44b8ebbfd6..ee9e375039f 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -8283,6 +8283,27 @@ GetConfigOptionFlags(const char *name, bool missing_ok)
 	return record->flags;
 }
 
+/*
+ * Get the source file and line associated with the given option.
+ *
+ * If the option doesn't exist, return 0 if missing_ok is true,
+ * otherwise 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 0;
+
+	*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 6bb81707b09..7255246f339 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -360,6 +360,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 void InitializeGUCOptions(void);
 extern bool SelectConfigFiles(const char *userDoption, const char *progname);
-- 
2.17.1

