v12-0002-PoC-fix-for-race-in-RelationBuildDesc-and-relcac.patch

application/octet-stream

Filename: v12-0002-PoC-fix-for-race-in-RelationBuildDesc-and-relcac.patch
Type: application/octet-stream
Part: 1
Message: Re: CREATE INDEX CONCURRENTLY does not index prepared xact's data

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: format-patch
Series: patch v12-0002
Subject: PoC fix for race in RelationBuildDesc() and relcache invalidation
File+
src/backend/utils/cache/relcache.c 28 0
From bd0961461e6c84d2cbe8cf20b5f6834c2fba8e03 Mon Sep 17 00:00:00 2001
From: Andrey Borodin <amborodin@acm.org>
Date: Fri, 30 Jul 2021 14:40:16 +0500
Subject: [PATCH v12 2/6] PoC fix for race in RelationBuildDesc() and relcache
 invalidation

---
 src/backend/utils/cache/relcache.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 13d9994af3..7eec7b1f41 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -997,9 +997,16 @@ equalRSDesc(RowSecurityDesc *rsdesc1, RowSecurityDesc *rsdesc2)
  *		(suggesting we are trying to access a just-deleted relation).
  *		Any other error is reported via elog.
  */
+typedef struct InProgressRels {
+	Oid relid;
+	bool invalidated;
+} InProgressRels;
+static InProgressRels inProgress[100];
+
 static Relation
 RelationBuildDesc(Oid targetRelId, bool insertIt)
 {
+	int in_progress_offset;
 	Relation	relation;
 	Oid			relid;
 	HeapTuple	pg_class_tuple;
@@ -1033,6 +1040,14 @@ RelationBuildDesc(Oid targetRelId, bool insertIt)
 	}
 #endif
 
+	for (in_progress_offset = 0;
+		 OidIsValid(inProgress[in_progress_offset].relid);
+		 in_progress_offset++)
+		;
+	inProgress[in_progress_offset].relid = targetRelId;
+retry:
+	inProgress[in_progress_offset].invalidated = false;
+
 	/*
 	 * find the tuple in pg_class corresponding to the given relation id
 	 */
@@ -1213,6 +1228,12 @@ RelationBuildDesc(Oid targetRelId, bool insertIt)
 	 */
 	heap_freetuple(pg_class_tuple);
 
+	if (inProgress[in_progress_offset].invalidated)
+		goto retry;				/* TODO free old one */
+	/* inProgress is in fact the stack, we can safely remove it's top */
+	inProgress[in_progress_offset].relid = InvalidOid;
+	Assert(inProgress[in_progress_offset + 1].relid == InvalidOid);
+
 	/*
 	 * Insert newly created relation into relcache hash table, if requested.
 	 *
@@ -2805,6 +2826,13 @@ RelationCacheInvalidateEntry(Oid relationId)
 		relcacheInvalsReceived++;
 		RelationFlushRelation(relation);
 	}
+	else
+	{
+		int i;
+		for (i = 0; OidIsValid(inProgress[i].relid); i++)
+			if (inProgress[i].relid == relationId)
+				inProgress[i].invalidated = true;
+	}
 }
 
 /*
-- 
2.24.3 (Apple Git-128)