[BUG] pg_rewind: file sync bypass and findLastCheckpoint boundary crash
Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.
You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:
docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t253605psql -h localhost -U postgresBuilt from patchset v1 (message #1), August 30, 2026 at 04:57 AM.
Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:
git clone --branch t253605_1 https://github.com/hackorum-dev/postgres.gitIn a checkout you already have, add the fork once:
git remote add hackorum https://github.com/hackorum-dev/postgres.gitthen, for this patchset and every later one:
git fetch hackorum t253605_1 && git checkout t253605_1Patchset v1 (message #1) is on t253605_1
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"
On Sun, Aug 30, 2026 at 10:15 AM Srinath Reddy Sadipiralla <
srinath2133@gmail.com> wrote:
Hi,
While working on [0], I have found a bug in pg_rewind where it
sorry forgot to add [0]/messages/by-id/CAFC+b6pztjF8AiM=GOs=SeNOYLpZnUSSMJsRKKZdf-MKJj22VQ@mail.gmail.com link.
[0]: /messages/by-id/CAFC+b6pztjF8AiM=GOs=SeNOYLpZnUSSMJsRKKZdf-MKJj22VQ@mail.gmail.com
/messages/by-id/CAFC+b6pztjF8AiM=GOs=SeNOYLpZnUSSMJsRKKZdf-MKJj22VQ@mail.gmail.com
--
Thanks :)
Srinath Reddy Sadipiralla
EDB: https://www.enterprisedb.com/