agora inbox for pgsql-hackers@postgresql.org  
help / color / mirror / Atom feed
[PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
327+ messages / 1 participants
[nested] [flat]

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread

* [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion
@ 2026-06-09 09:54  Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
  0 siblings, 0 replies; 327+ messages in thread

From: Bertrand Drouvot @ 2026-06-09 09:54 UTC (permalink / raw)

read_local_xlog_page_guts() has the same race as logical_read_xlog_page() (that
has been fixed in commit xxxxx): when RecoveryInProgress() returns true during
promotion, it gets the old timeline from GetXLogReplayRecPtr() while old WAL
segments may already be removed.

This affects SQL-callable logical decoding functions (pg_logical_slot_get_changes,
pg_logical_slot_peek_changes) running on a standby during promotion.

Apply the same fix: use GetWALInsertionTimeLineIfSet() to detect that the
insertion timeline is already established and use it directly.

Reported-by: Xuneng Zhou <xunengzhou@gmail.com>
Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Discussion: https://postgr.es/m/7daef094-abf3-4672-bc23-3df4763b16a3%40gmail.com
---
 src/backend/access/transam/xlogutils.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 100.0% src/backend/access/transam/

diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..fdc341d8fa4 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -896,7 +896,19 @@ read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
 		if (!RecoveryInProgress())
 			read_upto = GetFlushRecPtr(&currTLI);
 		else
+		{
+			TimeLineID	insertTLI;
+
 			read_upto = GetXLogReplayRecPtr(&currTLI);
+
+			/*
+			 * If the insertion timeline has already been set, use it. See
+			 * logical_read_xlog_page() for details.
+			 */
+			insertTLI = GetWALInsertionTimeLineIfSet();
+			if (insertTLI != 0)
+				currTLI = insertTLI;
+		}
 		tli = currTLI;
 
 		/*
-- 
2.34.1


--Wctt8FE9hhxDGrBZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
	filename="v2-0004-Add-SQL-path-test-for-read_local_xlog_page_guts-t.patch"



^ permalink  raw  reply  [nested|flat] 327+ messages in thread


end of thread, other threads:[~2026-06-09 09:54 UTC | newest]

Thread overview: 327+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
2026-06-09 09:54 [PATCH v2 3/4] Fix race condition in read_local_xlog_page_guts() timeline selection during promotion Bertrand Drouvot <bertranddrouvot.pg@gmail.com>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox