From f62b6b45594b4d58ffe739ca42ecd3aca6605c4c Mon Sep 17 00:00:00 2001 From: Anthonin Bonnefoy Date: Fri, 20 Feb 2026 18:15:12 +0100 Subject: Fix stuck shutdown due to unflushed records Shutdown sequence may be stuck indefinitely under the following circumstances: - Data checksums is enabled - A logical replication walsender is running - A select in an explicit ongoing transaction pruned a heap page and logged a FPI_FOR_HINT record. This record is likely going to be a contrecord and start a new page. Starting the shutdown will kill this ongoing transaction. Since the transaction doesn't have an allocated xid, the FPI_FOR_HINT record will be left unflushed. When the checkpointer starts ShutdownXLOG(), all walsenders will be notified to stop. However, the logical replication walsender will be stuck in an infinite loop, trying to read this unflushed record, never reaching the stop state and blocking the whole shutdown sequence. This patch fixes the issue by flushing all records before signaling walsenders to stop. --- src/backend/access/transam/xlog.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 13ec6225b85..aa490176aaf 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6727,6 +6727,8 @@ GetLastSegSwitchData(XLogRecPtr *lastSwitchLSN) void ShutdownXLOG(int code, Datum arg) { + XLogRecPtr WriteRqstPtr; + /* * We should have an aux process resource owner to use, and we should not * be in a transaction that's installed some other resowner. @@ -6740,6 +6742,15 @@ ShutdownXLOG(int code, Datum arg) ereport(IsPostmasterEnvironment ? LOG : NOTICE, (errmsg("shutting down"))); + /* + * We may have unflushed records, make sure everything is flushed before + * stopping the walsenders. + */ + SpinLockAcquire(&XLogCtl->info_lck); + WriteRqstPtr = XLogCtl->LogwrtRqst.Write; + SpinLockRelease(&XLogCtl->info_lck); + XLogFlush(WriteRqstPtr); + /* * Signal walsenders to move to stopping state. */ -- 2.52.0