Skip to content

Commit 84911ff

Browse files
committed
Improve relcache invalidation handling of currently invisible relations.
The corner case where a relcache invalidation tried to rebuild the entry for a referenced relation but couldn't find it in the catalog wasn't correct. The code tried to RelationCacheDelete/RelationDestroyRelation the entry. That didn't work when assertions are enabled because the latter contains an assertion ensuring the refcount is zero. It's also more generally a bad idea, because by virtue of being referenced somebody might actually look at the entry, which is possible if the error is trapped and handled via a subtransaction abort. Instead just error out, without deleting the entry. As the entry is marked invalid, the worst that can happen is that the invalid (and at some point unused) entry lingers in the relcache. Discussion: 22459.1418656530@sss.pgh.pa.us There should be no way to hit this case < 9.4 where logical decoding introduced a bug that can hit this. But since the code for handling the corner case is there it should do something halfway sane, so backpatch all the the way back. The logical decoding bug will be handled in a separate commit.
1 parent 0cc6cef commit 84911ff

File tree

1 file changed

+7
-3
lines changed

1 file changed

+7
-3
lines changed

src/backend/utils/cache/relcache.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2101,9 +2101,13 @@ RelationClearRelation(Relation relation, bool rebuild)
21012101
newrel = RelationBuildDesc(save_relid, false);
21022102
if (newrel == NULL)
21032103
{
2104-
/* Should only get here if relation was deleted */
2105-
RelationCacheDelete(relation);
2106-
RelationDestroyRelation(relation, false);
2104+
/*
2105+
* This shouldn't happen as dropping a relation is intended to be
2106+
* impossible if still referenced (c.f. CheckTableNotInUse()). But
2107+
* if we get here anyway, we can't just delete the relcache entry,
2108+
* as it possibly could get accessed later (as e.g. the error
2109+
* might get trapped and handled via a subtransaction rollback).
2110+
*/
21072111
elog(ERROR, "relation %u deleted while still in use", save_relid);
21082112
}
21092113

0 commit comments

Comments
 (0)