v11-0002-PoC-fix-for-race-in-RelationBuildDesc-and-relcac.patch
application/octet-stream
Filename: v11-0002-PoC-fix-for-race-in-RelationBuildDesc-and-relcac.patch
Type: application/octet-stream
Part: 1
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 v11-0002
Subject: PoC fix for race in RelationBuildDesc() and relcache invalidation
| File | + | − |
|---|---|---|
| src/backend/utils/cache/relcache.c | 28 | 0 |
From a917cae8fe1730fcf715aee2dabd1dd9d32e15b6 Mon Sep 17 00:00:00 2001
From: Andrey Borodin <amborodin@acm.org>
Date: Fri, 30 Jul 2021 14:40:16 +0500
Subject: [PATCH v11 2/5] 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 fd05615e76..a3347b793e 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.
*
@@ -2802,6 +2823,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)