inplace070-rel-locks-missing-v1.patch

text/plain

Filename: inplace070-rel-locks-missing-v1.patch
Type: text/plain
Part: 5
Message: Re: race condition in pg_class

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
Series: patch v1
File+
src/backend/catalog/heap.c 2 0
src/backend/catalog/index.c 1 0
src/backend/commands/indexcmds.c 4 0
src/backend/commands/sequence.c 1 0
Author:     Noah Misch <noah@leadboat.com>
Commit:     Noah Misch <noah@leadboat.com>

    Add relation locks where existing standards would have them.
    
    The SetRelationHasSubclass() header comment says to hold this
    ShareUpdateExclusiveLock lock, and it's conventional for the sort of DDL
    done there and in IndexSetParentIndex().  SequenceChangePersistence()
    and heap_create() are deep surgery warranting AccessExclusiveLock.  This
    might cause more deadlocks.  I didn't run down exact user-visible bugs
    reachable via these gaps.  Back-patch to v12 (all supported versions).
    
    Reviewed by FIXME.
    
    Discussion: https://postgr.es/m/FIXME

diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 922ba79..2652405 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -407,6 +407,8 @@ heap_create(const char *relname,
 	/* ensure that stats are dropped if transaction aborts */
 	pgstat_create_relation(rel);
 
+	LockRelationOid(relid, AccessExclusiveLock);
+
 	return rel;
 }
 
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 5a8568c..5c48e57 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1058,6 +1058,7 @@ index_create(Relation heapRelation,
 	if (OidIsValid(parentIndexRelid))
 	{
 		StoreSingleInheritance(indexRelationId, parentIndexRelid, 1);
+		LockRelationOid(parentIndexRelid, ShareUpdateExclusiveLock);
 		SetRelationHasSubclass(parentIndexRelid, true);
 	}
 
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index d9016ef..a28ce72 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -4475,7 +4475,10 @@ IndexSetParentIndex(Relation partitionIdx, Oid parentOid)
 
 	/* set relhassubclass if an index partition has been added to the parent */
 	if (OidIsValid(parentOid))
+	{
+		LockRelationOid(parentOid, ShareUpdateExclusiveLock);
 		SetRelationHasSubclass(parentOid, true);
+	}
 
 	/* set relispartition correctly on the partition */
 	update_relispartition(partRelid, OidIsValid(parentOid));
@@ -4527,6 +4530,7 @@ update_relispartition(Oid relationId, bool newval)
 	HeapTuple	tup;
 	Relation	classRel;
 
+	LockRelationOid(relationId, ShareUpdateExclusiveLock);
 	classRel = table_open(RelationRelationId, RowExclusiveLock);
 	tup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
 	if (!HeapTupleIsValid(tup))
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 4610356..a60d6e7 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -545,6 +545,7 @@ SequenceChangePersistence(Oid relid, char newrelpersistence)
 	Buffer		buf;
 	HeapTupleData seqdatatuple;
 
+	LockRelationOid(relid, AccessExclusiveLock);
 	init_sequence(relid, &elm, &seqrel);
 
 	/* check the comment above nextval_internal()'s equivalent call. */