Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit cd312ad

Browse files
committed
Prevent inconsistent use of stats entry for replication slots
Concurrent activity around replication slot creation and drop could cause a replication slot to use a stats entry it should not have used when created, triggering an assertion failure when retrieving an inconsistent entry from the dshash table used by the stats facility. The issue is that pgstat_drop_replslot() calls pgstat_drop_entry() without checking the result. If pgstat_drop_entry() cannot free the entry related to the object dropped, pgstat_request_entry_refs_gc() should be called. AtEOXact_PgStat_DroppedStats() and surrounding routines dropping stats entries already do that. This is documented in pgstat_internal.h, but let's add a comment at the top of pgstat_drop_entry() as that can be easy to miss. Reported-by: Alexander Lakhin Author: Floris Van Nee Analyzed-by: Andres Freund Discussion: https://postgr.es/m/17947-b9554521ad963c9c@postgresql.org Backpatch-through: 15
1 parent 8111e80 commit cd312ad

File tree

2 files changed

+14
-2
lines changed

2 files changed

+14
-2
lines changed

src/backend/utils/activity/pgstat_replslot.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,9 @@ pgstat_drop_replslot(ReplicationSlot *slot)
157157
{
158158
Assert(LWLockHeldByMeInMode(ReplicationSlotAllocationLock, LW_EXCLUSIVE));
159159

160-
pgstat_drop_entry(PGSTAT_KIND_REPLSLOT, InvalidOid,
161-
ReplicationSlotIndex(slot));
160+
if (!pgstat_drop_entry(PGSTAT_KIND_REPLSLOT, InvalidOid,
161+
ReplicationSlotIndex(slot)))
162+
pgstat_request_entry_refs_gc();
162163
}
163164

164165
/*

src/backend/utils/activity/pgstat_shmem.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,17 @@ pgstat_drop_database_and_contents(Oid dboid)
855855
pgstat_request_entry_refs_gc();
856856
}
857857

858+
/*
859+
* Drop a single stats entry.
860+
*
861+
* This routine returns false if the stats entry of the dropped object could
862+
* not be freed, true otherwise.
863+
*
864+
* The callers of this function should call pgstat_request_entry_refs_gc()
865+
* if the stats entry could not be freed, to ensure that this entry's memory
866+
* can be reclaimed later by a different backend calling
867+
* pgstat_gc_entry_refs().
868+
*/
858869
bool
859870
pgstat_drop_entry(PgStat_Kind kind, Oid dboid, Oid objoid)
860871
{

0 commit comments

Comments
 (0)