@@ -580,19 +580,6 @@ ReplicationSlotAcquire(const char *name, bool nowait, bool error_if_invalid)
580
580
name )));
581
581
}
582
582
583
- /* Invalid slots can't be modified or used before accessing the WAL. */
584
- if (error_if_invalid && s -> data .invalidated != RS_INVAL_NONE )
585
- {
586
- LWLockRelease (ReplicationSlotControlLock );
587
-
588
- ereport (ERROR ,
589
- errcode (ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE ),
590
- errmsg ("can no longer access replication slot \"%s\"" ,
591
- NameStr (s -> data .name )),
592
- errdetail ("This replication slot has been invalidated due to \"%s\"." ,
593
- GetSlotInvalidationCauseName (s -> data .invalidated )));
594
- }
595
-
596
583
/*
597
584
* This is the slot we want; check if it's active under some other
598
585
* process. In single user mode, we don't need this check.
@@ -650,12 +637,25 @@ ReplicationSlotAcquire(const char *name, bool nowait, bool error_if_invalid)
650
637
else if (!nowait )
651
638
ConditionVariableCancelSleep (); /* no sleep needed after all */
652
639
653
- /* Let everybody know we've modified this slot */
654
- ConditionVariableBroadcast (& s -> active_cv );
655
-
656
640
/* We made this slot active, so it's ours now. */
657
641
MyReplicationSlot = s ;
658
642
643
+ /*
644
+ * We need to check for invalidation after making the slot ours to avoid
645
+ * the possible race condition with the checkpointer that can otherwise
646
+ * invalidate the slot immediately after the check.
647
+ */
648
+ if (error_if_invalid && s -> data .invalidated != RS_INVAL_NONE )
649
+ ereport (ERROR ,
650
+ errcode (ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE ),
651
+ errmsg ("can no longer access replication slot \"%s\"" ,
652
+ NameStr (s -> data .name )),
653
+ errdetail ("This replication slot has been invalidated due to \"%s\"." ,
654
+ GetSlotInvalidationCauseName (s -> data .invalidated )));
655
+
656
+ /* Let everybody know we've modified this slot */
657
+ ConditionVariableBroadcast (& s -> active_cv );
658
+
659
659
/*
660
660
* The call to pgstat_acquire_replslot() protects against stats for a
661
661
* different slot, from before a restart or such, being present during
0 commit comments