On Wed, Jun 17, 2026 at 02:27:25PM +0200, Matthias van de Meent wrote: > On Wed, 17 Jun 2026 at 08:00, Alexander Lakhin <[email protected]> wrote: >> 1) An issue in lookup_type_cache() > > I believe this is caused by partial subsystem initialization. Attached > patch 0001 should address this failure without causing the server to > restart on OOM.
Hmm. I think that this is an ordering problem. We could make the callbacks be registered last, once we are sure that the two hash tables and the in-progress list have been initialized. I am not sure that this requires a new facility; it is also an advantage to keep the initialization sequence in a one code path, without an abstraction. RelIdToTypeIdCacheHash and RelIdToTypeIdCacheHash are in the TopMemoryContext, static to the process, so we could just check them for NULL-ness to make the initialization repeatable. That gives me the attached v2. Reusing Alexander's randomness trick, that looks stable here. >> 2) An issue in GetSnapshotData() > > Again, caused by partial initialization, though in this case it's of a > SnapshotData* which is later checked again. Attached patch 0002 should > address this failure. Yeah, that seems right to make repeated calls of GetSnapshotData() able to work. LGTM. >> 3) An issue in StandbyAcquireAccessExclusiveLock() > <snip> > > I'm not sure how to solve this correctly; I think ideally the > StandbyAcquireAccessExclusiveLock() hash code would be wrapped by a > critical section, but I'm not 100% sure if that will be a sufficient > approach; and it'd definitely need some code to allow the various > hashmaps' memctxs to alloc during critical sections. Not checked this one yet. Thoughts about the first part? -- Michael
From 8b2ecd4df82750ca98cf7e67244cb46b1e4239ed Mon Sep 17 00:00:00 2001 From: Michael Paquier <[email protected]> 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
signature.asc
Description: PGP signature
