diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2011-03-22 13:01:12 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2011-03-22 13:01:12 -0400 |
commit | ab6657ea13236b3603c148bba98decc574476acd (patch) | |
tree | f196d3547197841e6fee32b4c5c25d82cf0bdc2e /src/backend/utils/cache/catcache.c | |
parent | 7135bc5d6665fb9cf9452b660c0f7c3daa4a439b (diff) | |
download | postgresql-ab6657ea13236b3603c148bba98decc574476acd.tar.gz postgresql-ab6657ea13236b3603c148bba98decc574476acd.zip |
Avoid potential deadlock in InitCatCachePhase2().
Opening a catcache's index could require reading from that cache's own
catalog, which of course would acquire AccessShareLock on the catalog.
So the original coding here risks locking index before heap, which could
deadlock against another backend trying to get exclusive locks in the
normal order. Because InitCatCachePhase2 is only called when a backend
has to start up without a relcache init file, the deadlock was seldom seen
in the field. (And by the same token, there's no need to worry about any
performance disadvantage; so not much point in trying to distinguish
exactly which catalogs have the risk.)
Bug report, diagnosis, and patch by Nikhil Sontakke. Additional commentary
by me. Back-patch to all supported branches.
Diffstat (limited to 'src/backend/utils/cache/catcache.c')
-rw-r--r-- | src/backend/utils/cache/catcache.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index 6fd672435fe..97de82e4e5f 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -26,6 +26,7 @@ #ifdef CATCACHE_STATS #include "storage/ipc.h" /* for on_proc_exit */ #endif +#include "storage/lmgr.h" #include "utils/builtins.h" #include "utils/fmgroids.h" #include "utils/memutils.h" @@ -1032,8 +1033,16 @@ InitCatCachePhase2(CatCache *cache, bool touch_index) { Relation idesc; + /* + * We must lock the underlying catalog before opening the index to + * avoid deadlock, since index_open could possibly result in reading + * this same catalog, and if anyone else is exclusive-locking this + * catalog and index they'll be doing it in that order. + */ + LockRelationOid(cache->cc_reloid, AccessShareLock); idesc = index_open(cache->cc_indexoid, AccessShareLock); index_close(idesc, AccessShareLock); + UnlockRelationOid(cache->cc_reloid, AccessShareLock); } } |