]> granicus.if.org Git - postgresql/commitdiff
Prevent starting a standalone backend with standby_mode on.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 31 Aug 2016 12:52:13 +0000 (08:52 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 31 Aug 2016 12:52:13 +0000 (08:52 -0400)
This can't really work because standby_mode expects there to be more
WAL arriving, which there will not ever be because there's no WAL
receiver process to fetch it.  Moreover, if standby_mode is on then
hot standby might also be turned on, causing even more strangeness
because that expects read-only sessions to be executing in parallel.
Bernd Helmle reported a case where btree_xlog_delete_get_latestRemovedXid
got confused, but rather than band-aiding individual problems it seems
best to prevent getting anywhere near this state in the first place.
Back-patch to all supported branches.

In passing, also fix some omissions of errcodes in other ereport's in
readRecoveryCommandFile().

Michael Paquier (errcode hacking by me)

Discussion: <00F0B2CEF6D0CEF8A90119D4@eje.credativ.lan>

src/backend/access/transam/xlog.c

index 1e79ebdc8fb0c1beaa279f5a7557295fab1ad159..a40002202bff08e5b1b1b8943d732b285c03c793 100644 (file)
@@ -5347,7 +5347,8 @@ readRecoveryCommandFile(void)
                                rtli = (TimeLineID) strtoul(item->value, NULL, 0);
                                if (errno == EINVAL || errno == ERANGE)
                                        ereport(FATAL,
-                                                       (errmsg("recovery_target_timeline is not a valid number: \"%s\"",
+                                                       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                        errmsg("recovery_target_timeline is not a valid number: \"%s\"",
                                                                        item->value)));
                        }
                        if (rtli)
@@ -5363,7 +5364,8 @@ readRecoveryCommandFile(void)
                        recoveryTargetXid = (TransactionId) strtoul(item->value, NULL, 0);
                        if (errno == EINVAL || errno == ERANGE)
                                ereport(FATAL,
-                                (errmsg("recovery_target_xid is not a valid number: \"%s\"",
+                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                 errmsg("recovery_target_xid is not a valid number: \"%s\"",
                                                 item->value)));
                        ereport(DEBUG2,
                                        (errmsg_internal("recovery_target_xid = %u",
@@ -5454,7 +5456,8 @@ readRecoveryCommandFile(void)
                }
                else
                        ereport(FATAL,
-                                       (errmsg("unrecognized recovery parameter \"%s\"",
+                                       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                        errmsg("unrecognized recovery parameter \"%s\"",
                                                        item->name)));
        }
 
@@ -5473,10 +5476,20 @@ readRecoveryCommandFile(void)
        {
                if (recoveryRestoreCommand == NULL)
                        ereport(FATAL,
-                                       (errmsg("recovery command file \"%s\" must specify restore_command when standby mode is not enabled",
+                                       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                        errmsg("recovery command file \"%s\" must specify restore_command when standby mode is not enabled",
                                                        RECOVERY_COMMAND_FILE)));
        }
 
+       /*
+        * We don't support standby_mode in standalone backends; that requires
+        * other processes such as the WAL receiver to be alive.
+        */
+       if (StandbyMode && !IsUnderPostmaster)
+               ereport(FATAL,
+                               (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                       errmsg("standby mode is not supported by single-user servers")));
+
        /* Enable fetching from archive recovery area */
        InArchiveRecovery = true;
 
@@ -5493,7 +5506,8 @@ readRecoveryCommandFile(void)
                        /* Timeline 1 does not have a history file, all else should */
                        if (rtli != 1 && !existsTimeLineHistory(rtli))
                                ereport(FATAL,
-                                               (errmsg("recovery target timeline %u does not exist",
+                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                errmsg("recovery target timeline %u does not exist",
                                                                rtli)));
                        recoveryTargetTLI = rtli;
                        recoveryTargetIsLatest = false;