Thread

Commits

Same data as JSON: GET /api/v1/messages/:b64id/commits the thread's linked commits as JSON, with link sources. API reference →
  1. Fix a race condition in updating procArray->replication_slot_xmin.

  1. Fix the race condition for updating slot minimum LSN

    Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> — 2026-01-27T06:32:31Z

    Hi,
    
    During a discussion about a similar issue involving the invalidation of newly
    created slots[1], we found another race condition that might lead to the same
    problem.
    
    The race condition is that: if a backend creates a new slot and attempts to
    initialize the slot.restart_lsn during WAL reservation, but meanwhile, another
    backend invokes ReplicationSlotsComputeRequiredLSN(), the slot minimum LSN may
    be initially updated by the newly created slot, only to be subsequently
    overwritten by the backend running ReplicationSlotsComputeRequiredLSN() with an
    more recent LSN. This scenario could lead to the premature removal of WALs
    reserved by the new slot during a checkpoint, resulting in the newly created
    slot being invalidated.
     
    The steps to reproduce are as follows:
     
        1. Create a slot 'advtest' for later advancement.
        select pg_create_logical_replication_slot('advtest', 'test_decoding');
        2. Start a backend to create a slot (s) but block it before updating the
        restart_lsn in ReplicationSlotReserveWal().
            select pg_create_logical_replication_slot('s', 'test_decoding');
        3. start another backend to generate some new WAL files and advance the
        slot (advtest) to the latest position but block it from updating the LSN in
        XLogSetReplicationSlotMinimumLSN()
            select pg_switch_wal();
            select pg_switch_wal();
            SELECT pg_log_standby_snapshot();
            SELECT pg_log_standby_snapshot();
            select pg_replication_slot_advance('advtest', pg_current_wal_lsn());
            select pg_replication_slot_advance('advtest', pg_current_wal_lsn());
        4. Release the backend to create slot (s).
        5. execute checkpoint but block it before calling XLogGetReplicationSlotMinimumLSN()
        6. release the advancement backend and then the LSN will be set to a new position.
        7. release the checkpoint and the WALs required by the slot (s) are removed.
    
    This issue is similar to the concurrent slot_xmin update issue fixed in commit
    2a5225b, so I think it's better to apply a similar fix, e.g., we can acquire an
    exclusive ReplicationSlotControlLock when updating slot.restart_lsn during WAL
    reservation. Additionally, XLogSetReplicationSlotMinimumLSN() is placed under
    the protection of the ReplicationSlotControlLock. This serializes the update of
    slot.restart_lsn and the computation of the minimum LSN in other backends,
    ensuring that a more recent minimum LSN isn't computed while an older one is
    still being reserved.
    
    The above fix is implemented in the attached patch 0001.
    
    [1] https://www.postgresql.org/message-id/flat/TY4PR01MB16907DCA80DBC3E77CE6B203294C9A%40TY4PR01MB16907.jpnprd01.prod.outlook.com
    
    Best Regards,
    Hou zj
    
  2. Re: Fix the race condition for updating slot minimum LSN

    surya poondla <suryapoondla4@gmail.com> — 2026-04-14T23:25:44Z

    Hi Hou zj,
    
    Thanks for the patch. The fix looks correct and the approach mirrors the
    one taken in commit 2a5225b for the xmin race.
    
    I have a question about copy_replication_slot() in slotfuncs.c, the
    restart_lsn is written under only the spinlock, followed by
    ReplicationSlotsComputeRequiredLSN() the same pattern that this patch
    fixes. Could this path be affected by the same race?
    
    Looking at the code, I think it is safe because
    create_logical_replication_slot() is called with src_restart_lsn which is
    always a valid LSN (if not valid, an error is thrown). Inside
    CreateInitDecodingContext(), since restart_lsn is valid,
    ReplicationSlotReserveWal() is skipped and the slot's restart_lsn is set
    directly to src_restart_lsn. So by the time the write of the slot happens,
    the destination slot already has a valid non-zero restart_lsn, the
    InvalidXLogRecPtr window never exists. Additionally, line the code errors
    out if copy_restart_lsn < src_restart_lsn, so the write never moves
    restart_lsn backward, meaning a concurrent scanner will always see a valid
    LSN and never skip this slot.
    
    If that reasoning is correct, a comment near the
    ReplicationSlotsComputeRequiredLSN() in copy_replication_slot() explaining
    why it does not need the same protection would help future readers.
    
    Regards,
    Surya Poondla
    
  3. Re: Fix the race condition for updating slot minimum LSN

    solai v <solai.cdac@gmail.com> — 2026-05-15T04:43:25Z

    Hi Hou zj,
    I tested the patch on a local debug build.The patch applied cleanly
    and postgreSQL built successfully without issues.
    I tested logical slot creation,WAL switching,slot advancement,and
    checkpoints after applying the patch,and everything worked as expected
    without crashes or assertion failures.
    I also reviewed the changes in slot.c and slotsync.c .The locking
    approach around restart_lsn updates and minimum LSN computation looks
    reasonable to me and seems consistent with the existing xmin
    synchronization logic.
    Surya's explanation regarding copy_replication_slot() also makes sense
    to me after reviewing that patch.
    
    Regards,
    Solai