[BUG] pg_rewind: file sync bypass and findLastCheckpoint boundary crash

From: Srinath Reddy Sadipiralla <srinath2133(at)gmail(dot)com>
To: pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>
Cc: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: [BUG] pg_rewind: file sync bypass and findLastCheckpoint boundary crash
Date: 2026-08-30 04:45:13
Message-ID: CAFC+b6qpqH4E22-PAemSby8Yv_2Z_8PUy8XrUmpW9Ot_efKdug@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

While working on [0], I have found a bug in pg_rewind where it
bypasses the file sync phase if the target cluster's WAL ends
exactly at the divergence point. Fixing this logic exposed another
crash bug in findLastCheckpoint().

Bug 1: The File Sync Bypass
If you cleanly shut down a primary and promote a standby, the
target's WAL ends exactly where the new timeline branches.
In pg_rewind.c, the timeline divergence logic contains this check:

if (target_wal_endrec > divergerec) {
rewind_needed = true;
} else {
Assert(target_wal_endrec == divergerec);
rewind_needed = false;
}

If rewind_needed is false, pg_rewind exits immediately. While it's
true there are no modified data blocks to rewind, exiting here
bypasses the file sync phase. The target cluster is left without the
source's new timeline history file, any non-WAL-logged file modifications
(like postgresql.auto.conf), and pg_rewind fails to update the target's
pg_control file with the new timeline and DB_IN_ARCHIVE_RECOVERY state.

Bug 2: The findLastCheckpoint Crash
If we fix Bug 1 by simply removing the rewind_needed = false
so the file sync can run, pg_rewind crashes immediately with
error: could not find previous WAL record at <LSN>: invalid record length
at <LSN>: expected at least 24, got 0

This happens because findLastCheckpoint attempts to read
backward starting at divergerec. But because the target shut
down cleanly, divergerec points exactly to the end of the written WAL.
The reader hits unwritten zeroes, expects a 24-byte record header, and
throws a fatal error. The original early exit was masking this hide in the
backward scanner.

The attached patch has a reproducer with as a TAP test and
resolves both issues, thoughts?

--
Thanks :)
Srinath Reddy Sadipiralla
EDB: https://www.enterprisedb.com/
"i have no special talent i am only passionately curious - Albert Einstein"

Attachment Content-Type Size
v1-0001-Fix-pg_rewind-file-sync-bypass-and-findLastCheckpoin.patch application/octet-stream 13.8 KB

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Srinath Reddy Sadipiralla 2026-08-30 04:46:52 Re: [BUG] pg_rewind: file sync bypass and findLastCheckpoint boundary crash
Previous Message Srinath Reddy Sadipiralla 2026-08-30 04:24:00 pg_rewind: Remove recovery at the start of rewind