From a917cae8fe1730fcf715aee2dabd1dd9d32e15b6 Mon Sep 17 00:00:00 2001 From: Andrey Borodin 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)