From 557ecbbead1ed01c0d11763fe65f02b7db6184c1 Mon Sep 17 00:00:00 2001 From: Shveta Malik Date: Wed, 23 Sep 2026 15:46:51 +0530 Subject: [PATCH] helper function --- src/backend/replication/logical/slotsync.c | 63 ++++++++++++++-------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/slotsync.c b/src/backend/replication/logical/slotsync.c index 9121a80ec36..b4731687865 100644 --- a/src/backend/replication/logical/slotsync.c +++ b/src/backend/replication/logical/slotsync.c @@ -671,6 +671,47 @@ reserve_wal_for_local_slot(XLogRecPtr restart_lsn) LWLockRelease(ReplicationSlotAllocationLock); } +/* + * Persist the invalidated state of a synchronized slot to disk. + * + * This encapsulates the required I/O lock management and error handling. + * If the disk write fails, we must explicitly release the I/O lock + * before re-throwing the error to avoid deadlock with concurrent + * Checkpointer processes waiting for the I/O lock while holding + * ReplicationSlotAllocationLock. + */ +static void +persist_slot_invalidation(ReplicationSlot *slot, ReplicationSlotInvalidationCause cause) +{ + Assert(slot != NULL); + + LWLockAcquire(&slot->io_in_progress_lock, LW_EXCLUSIVE); + + PG_TRY(); + { + /* + * It persists the invalidated state to disk before publishing it in + * shared memory to ensure state durability on crash. + */ + ReplicationSlotPersistInvalidation(cause, + false); + } + PG_CATCH(); + { + /* + * Release ownership before making the I/O lock available to + * concurrent invalidators. + */ + HOLD_INTERRUPTS(); /* match the upcoming RESUME_INTERRUPTS */ + ReplicationSlotRelease(); + LWLockRelease(&slot->io_in_progress_lock); + PG_RE_THROW(); + } + PG_END_TRY(); + + LWLockRelease(&slot->io_in_progress_lock); +} + /* * If the remote restart_lsn and catalog_xmin have caught up with the * local ones, then update the LSNs and persist the local synced slot for @@ -829,27 +870,7 @@ synchronize_one_slot(RemoteSlot *remote_slot, Oid remote_dbid, if (slot->data.invalidated == RS_INVAL_NONE && remote_slot->invalidated != RS_INVAL_NONE) { - LWLockAcquire(&slot->io_in_progress_lock, LW_EXCLUSIVE); - - PG_TRY(); - { - ReplicationSlotPersistInvalidation(remote_slot->invalidated, - false); - } - PG_CATCH(); - { - /* - * Release ownership before making the I/O lock available to - * concurrent invalidators. - */ - HOLD_INTERRUPTS(); /* match the upcoming RESUME_INTERRUPTS */ - ReplicationSlotRelease(); - LWLockRelease(&slot->io_in_progress_lock); - PG_RE_THROW(); - } - PG_END_TRY(); - - LWLockRelease(&slot->io_in_progress_lock); + persist_slot_invalidation(slot, remote_slot->invalidated); ReplicationSlotsComputeRequiredXmin(false); ReplicationSlotsComputeRequiredLSN(); -- 2.34.1