On Wed, Sep 14, 2022 at 06:12:09PM -0400, Tom Lane wrote:
> Nathan Bossart <nathandboss...@gmail.com> writes:
>> On Wed, Sep 14, 2022 at 04:47:23PM -0400, Tom Lane wrote:
>>> Yeah, the objection there is only to trying to enforce such
>>> interrelationships in GUC hooks.  In this case it seems to me that
>>> we could easily check and complain at the point where we're about
>>> to use the GUC values.
> 
>> I think the cleanest way to do something like that would be to load a
>> check_configured_cb that produces a WARNING.  IIRC failing in
>> LoadArchiveLibrary() would just cause the archiver process to restart over
>> and over.  HandlePgArchInterrupts() might need some work as well.
> 
> Hm.  Maybe consistency-check these settings in the postmaster, sometime
> after we've absorbed all GUC settings but before we launch any children?
> That could provide a saner implementation for the recovery_target_*
> variables too.

Both archive_command and archive_library are PGC_SIGHUP, so IIUC that
wouldn't be sufficient.  I attached a quick sketch that seems to provide
the desired behavior.  It's nowhere near committable yet, but it
demonstrates what I'm thinking.

For recovery_target_*, something like you are describing seems reasonable.
I believe PostmasterMain() already performs some similar checks.

-- 
Nathan Bossart
Amazon Web Services: https://aws.amazon.com
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index 6ce361707d..1d0c6029a5 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -422,8 +422,15 @@ pgarch_ArchiverCopyLoop(void)
 			HandlePgArchInterrupts();
 
 			/* can't do anything if not configured ... */
-			if (ArchiveContext.check_configured_cb != NULL &&
-				!ArchiveContext.check_configured_cb())
+			if (XLogArchiveLibrary[0] != '\0' && XLogArchiveCommand[0] != '\0')
+			{
+				ereport(WARNING,
+						(errmsg("archive_mode enabled, but archiving is misconfigured"),
+						 errdetail("Only one of archive_command, archive_library may be set.")));
+				return;
+			}
+			else if (ArchiveContext.check_configured_cb != NULL &&
+					 !ArchiveContext.check_configured_cb())
 			{
 				ereport(WARNING,
 						(errmsg("archive_mode enabled, yet archiving is not configured")));
@@ -794,6 +801,9 @@ HandlePgArchInterrupts(void)
 	{
 		char	   *archiveLib = pstrdup(XLogArchiveLibrary);
 		bool		archiveLibChanged;
+		bool		misconfiguredBeforeReload = (XLogArchiveCommand[0] != '\0' &&
+												 XLogArchiveLibrary[0] != '\0');
+		bool		misconfiguredAfterReload;
 
 		ConfigReloadPending = false;
 		ProcessConfigFile(PGC_SIGHUP);
@@ -801,7 +811,11 @@ HandlePgArchInterrupts(void)
 		archiveLibChanged = strcmp(XLogArchiveLibrary, archiveLib) != 0;
 		pfree(archiveLib);
 
-		if (archiveLibChanged)
+		misconfiguredAfterReload = (XLogArchiveCommand[0] != '\0' &&
+									XLogArchiveLibrary[0] != '\0');
+
+		if ((archiveLibChanged && !misconfiguredAfterReload) ||
+			misconfiguredBeforeReload != misconfiguredAfterReload)
 		{
 			/*
 			 * Call the currently loaded archive module's shutdown callback,
@@ -816,10 +830,17 @@ HandlePgArchInterrupts(void)
 			 * internal_load_library()).  To deal with this, we simply restart
 			 * the archiver.  The new archive module will be loaded when the
 			 * new archiver process starts up.
+			 *
+			 * Similarly, we restart the archiver if our misconfiguration status
+			 * changes.  If the parameters were misconfigured but are no longer,
+			 * we must restart to load the correct callbacks.  If the parameters
+			 * weren't misconfigured but now are, we must restart to unload the
+			 * current callbacks.
 			 */
 			ereport(LOG,
 					(errmsg("restarting archiver process because value of "
-							"\"archive_library\" was changed")));
+							"\"archive_library\" or \"archive_command\" was "
+							"changed")));
 
 			proc_exit(0);
 		}
@@ -838,6 +859,14 @@ LoadArchiveLibrary(void)
 
 	memset(&ArchiveContext, 0, sizeof(ArchiveModuleCallbacks));
 
+	/*
+	 * If both a shell command and an archive library are specified, it is not
+	 * clear what we should do, so do nothing.  The archiver will emit WARNINGs
+	 * about the misconfiguration.
+	 */
+	if (XLogArchiveLibrary[0] != '\0' && XLogArchiveCommand[0] != '\0')
+		return;
+
 	/*
 	 * If shell archiving is enabled, use our special initialization function.
 	 * Otherwise, load the library and call its _PG_archive_module_init().

Reply via email to