From ab2e9488962ac04487f448304fbf1ffd59758ccc Mon Sep 17 00:00:00 2001
From: Nathan Bossart <nathandbossart@gmail.com>
Date: Sun, 10 Apr 2022 14:27:58 -0700
Subject: [PATCH v1 3/3] Block attempts to set GUCs while loading
 shared_preload_libraries.

This change attempts to block parameter changes in preloaded
libraries' _PG_init() functions.  We cannot reliably support such
behavior because certain parameters contribute to global values
we've already calculated at this point (e.g., MaxBackends).  We'd
rather make sure values like MaxBackends are available for use in
_PG_init(), and we encourage extension authors to instead recommend
suitable settings and error if such recommendations are not heeded.
Of course, preloaded libraries could still change the value
directly instead of via SetConfigOption(), but trying to handle
that is probably more trouble than it's worth.
---
 src/backend/utils/misc/guc.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 9e0f262088..b46ae700d7 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -253,6 +253,11 @@ static ConfigVariable *ProcessConfigFileInternal(GucContext context,
  */
 static bool check_wal_consistency_checking_deferred = false;
 
+/*
+ * Track whether we are currently defining a custom GUC.
+ */
+static bool defining_custom_guc = false;
+
 /*
  * Options for enum values defined in this module.
  *
@@ -7567,6 +7572,25 @@ set_config_option(const char *name, const char *value,
 	bool		prohibitValueChange = false;
 	bool		makeDefault;
 
+	/*
+	 * We attempt to block parameter changes in preloaded libraries' _PG_init()
+	 * functions.  We cannot reliably support such behavior because certain
+	 * parameters contribute to global values we've already calculated at this
+	 * point (e.g., MaxBackends).  We'd rather make sure values like MaxBackends
+	 * are available for use in _PG_init(), and we encourage extension authors
+	 * to instead recommend suitable settings and error if such recommendations
+	 * are not heeded.  Of course, preloaded libraries could still change the
+	 * value directly instead of via SetConfigOption(), but trying to handle
+	 * that is probably more trouble than it's worth.
+	 *
+	 * Since defining custom GUCs involves setting the GUC, we make sure to
+	 * avoid ERROR-ing while doing so.
+	 */
+	if (process_shared_preload_libraries_in_progress && !defining_custom_guc)
+		ereport(ERROR,
+				(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
+				 errmsg("cannot change parameters in _PG_init()")));
+
 	if (elevel == 0)
 	{
 		if (source == PGC_S_DEFAULT || source == PGC_S_FILE)
@@ -9297,6 +9321,8 @@ define_custom_variable(struct config_generic *variable)
 	struct config_string *pHolder;
 	struct config_generic **res;
 
+	defining_custom_guc = true;
+
 	/*
 	 * See if there's a placeholder by the same name.
 	 */
@@ -9380,6 +9406,7 @@ define_custom_variable(struct config_generic *variable)
 	set_string_field(pHolder, &pHolder->reset_val, NULL);
 
 	free(pHolder);
+	defining_custom_guc = false;
 }
 
 /*
-- 
2.25.1

