From 0fc95289424b7a66c875dc8a3de0cec5cbedfd3a Mon Sep 17 00:00:00 2001
From: Imran Zaheer <imran.zhir@gmail.com>
Date: Sat, 15 Aug 2026 11:52:16 +0500
Subject: [PATCH v1] Fix checkpointer restartpoint assertion failure.

The checkpointer fails with an assertion failure when it tries to
take a restartpoint during a crash recovery. This happens because the
checkpointer is not aware of whether an archive recovery was
requested or not, and whether hot standby initialization was done.

To fix this we track ArchiveRecoveryRequested in XLogRecoveryCtl so the
checkpointer can determine whether hot standby initialization was
performed and skip TruncateSUBTRANS() when archive recovery was not
requested.
---
 src/backend/access/transam/xlog.c         |  2 +-
 src/backend/access/transam/xlogrecovery.c | 32 +++++++++++++++++++++++
 src/include/access/xlogrecovery.h         |  7 +++++
 3 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index c3baca5193b..5287b475195 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -8366,7 +8366,7 @@ CreateRestartPoint(int flags)
 	 * in subtrans.c).  When hot standby is disabled, though, we mustn't do
 	 * this because StartupSUBTRANS hasn't been called yet.
 	 */
-	if (EnableHotStandby)
+	if (EnableHotStandby && ArchiveRecoveryWasRequested())
 		TruncateSUBTRANS(GetOldestTransactionIdConsideredRunning());
 
 	/* Real work is done; log and update stats. */
diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c
index 6de13b91748..1904d91e3ed 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -394,6 +394,7 @@ static bool HotStandbyActiveInReplay(void);
 static void SetCurrentChunkStartTime(TimestampTz xtime);
 static void SetLatestXTime(TimestampTz xtime);
 static RecoveryTargetType DetermineRecoveryTargetType(void);
+static void	SetArchiveRecoveryWasRequested(void);
 
 /*
  * Register shared memory for WAL recovery
@@ -982,6 +983,9 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
 	*wasShutdown_ptr = wasShutdown;
 	*haveBackupLabel_ptr = haveBackupLabel;
 	*haveTblspcMap_ptr = haveTblspcMap;
+
+	if (ArchiveRecoveryRequested)
+		SetArchiveRecoveryWasRequested();
 }
 
 /*
@@ -4451,6 +4455,34 @@ SetPromoteIsTriggered(void)
 	LocalPromoteIsTriggered = true;
 }
 
+bool
+ArchiveRecoveryWasRequested(void)
+{
+	/*
+	 * We only set local ArchiveRecoveryRequested once in the startup while
+	 * reading recovery signal files. So there's no need to keep checking after
+	 * the shared variable has once been seen true.
+	 */
+	if (ArchiveRecoveryRequested)
+		return true;
+
+	SpinLockAcquire(&XLogRecoveryCtl->info_lck);
+	ArchiveRecoveryRequested = XLogRecoveryCtl->SharedArchiveRecoveryRequested;
+	SpinLockRelease(&XLogRecoveryCtl->info_lck);
+
+	return ArchiveRecoveryRequested;
+}
+
+void
+SetArchiveRecoveryWasRequested(void)
+{
+	SpinLockAcquire(&XLogRecoveryCtl->info_lck);
+	XLogRecoveryCtl->SharedArchiveRecoveryRequested = true;
+	SpinLockRelease(&XLogRecoveryCtl->info_lck);
+
+	ArchiveRecoveryRequested = true;
+}
+
 /*
  * Check whether a promote request has arrived.
  */
diff --git a/src/include/access/xlogrecovery.h b/src/include/access/xlogrecovery.h
index a1d8a81dbc1..1e0b455506e 100644
--- a/src/include/access/xlogrecovery.h
+++ b/src/include/access/xlogrecovery.h
@@ -77,6 +77,12 @@ typedef struct XLogRecoveryCtlData
 	 */
 	bool		SharedPromoteIsTriggered;
 
+	/*
+	 * SharedArchiveRecoveryRequested indicates if the ArchiveRecoveryRequested
+	 * was set during startup InitWalRecovery(). Protected by info_lck.
+	 */
+	bool		SharedArchiveRecoveryRequested;
+
 	/*
 	 * recoveryWakeupLatch is used to wake up the startup process to continue
 	 * WAL replay, if it is waiting for WAL to arrive or promotion to be
@@ -220,6 +226,7 @@ extern XLogRecPtr GetCurrentReplayRecPtr(TimeLineID *replayEndTLI);
 
 extern bool PromoteIsTriggered(void);
 extern bool CheckPromoteSignal(void);
+extern bool ArchiveRecoveryWasRequested(void);
 extern void WakeupRecovery(void);
 
 extern void StartupRequestWalReceiverRestart(void);
-- 
2.34.1

