From 8b2ecd4df82750ca98cf7e67244cb46b1e4239ed Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Thu, 18 Jun 2026 13:24:47 +0900 Subject: [PATCH v2] typcache: Make initialization more resilient on OOM --- src/backend/utils/cache/typcache.c | 57 +++++++++++++++++------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c index da91a2ff1dd8..b96554a4b32e 100644 --- a/src/backend/utils/cache/typcache.c +++ b/src/backend/utils/cache/typcache.c @@ -392,50 +392,59 @@ lookup_type_cache(Oid type_id, int flags) bool found; int in_progress_offset; - if (TypeCacheHash == NULL) + if (in_progress_list == NULL) { /* First time through: initialize the hash table */ HASHCTL ctl; int allocsize; - ctl.keysize = sizeof(Oid); - ctl.entrysize = sizeof(TypeCacheEntry); + if (TypeCacheHash == NULL) + { + ctl.keysize = sizeof(Oid); + ctl.entrysize = sizeof(TypeCacheEntry); - /* - * TypeCacheEntry takes hash value from the system cache. For - * TypeCacheHash we use the same hash in order to speedup search by - * hash value. This is used by hash_seq_init_with_hash_value(). - */ - ctl.hash = type_cache_syshash; + /* + * TypeCacheEntry takes hash value from the system cache. For + * TypeCacheHash we use the same hash in order to speedup search + * by hash value. This is used by + * hash_seq_init_with_hash_value(). + */ + ctl.hash = type_cache_syshash; - TypeCacheHash = hash_create("Type information cache", 64, - &ctl, HASH_ELEM | HASH_FUNCTION); + TypeCacheHash = hash_create("Type information cache", 64, + &ctl, HASH_ELEM | HASH_FUNCTION); + } - Assert(RelIdToTypeIdCacheHash == NULL); - - ctl.keysize = sizeof(Oid); - ctl.entrysize = sizeof(RelIdToTypeIdCacheEntry); - RelIdToTypeIdCacheHash = hash_create("Map from relid to OID of cached composite type", 64, - &ctl, HASH_ELEM | HASH_BLOBS); - - /* Also set up callbacks for SI invalidations */ - CacheRegisterRelcacheCallback(TypeCacheRelCallback, (Datum) 0); - CacheRegisterSyscacheCallback(TYPEOID, TypeCacheTypCallback, (Datum) 0); - CacheRegisterSyscacheCallback(CLAOID, TypeCacheOpcCallback, (Datum) 0); - CacheRegisterSyscacheCallback(CONSTROID, TypeCacheConstrCallback, (Datum) 0); + if (RelIdToTypeIdCacheHash == NULL) + { + ctl.keysize = sizeof(Oid); + ctl.entrysize = sizeof(RelIdToTypeIdCacheEntry); + RelIdToTypeIdCacheHash = hash_create("Map from relid to OID of cached composite type", 64, + &ctl, HASH_ELEM | HASH_BLOBS); + } /* Also make sure CacheMemoryContext exists */ if (!CacheMemoryContext) CreateCacheMemoryContext(); /* - * reserve enough in_progress_list slots for many cases + * Reserve enough in_progress_list slots for many cases. This is + * the last allocation on purpose, done after the two others. */ allocsize = 4; in_progress_list = MemoryContextAlloc(CacheMemoryContext, allocsize * sizeof(*in_progress_list)); in_progress_list_maxlen = allocsize; + + /* + * Set up callbacks for SI invalidations. These are done last, + * once all the other initializations are done. + */ + CacheRegisterRelcacheCallback(TypeCacheRelCallback, (Datum) 0); + CacheRegisterSyscacheCallback(TYPEOID, TypeCacheTypCallback, (Datum) 0); + CacheRegisterSyscacheCallback(CLAOID, TypeCacheOpcCallback, (Datum) 0); + CacheRegisterSyscacheCallback(CONSTROID, TypeCacheConstrCallback, (Datum) 0); } Assert(TypeCacheHash != NULL && RelIdToTypeIdCacheHash != NULL); -- 2.54.0