From db9b5e1304fd4ddadff2eae0359ea5e7a48ffbc6 Mon Sep 17 00:00:00 2001 From: David Rowley Date: Mon, 24 Aug 2026 23:38:53 +1200 Subject: [PATCH] RFC: Add BUG_WARNING elevel We really should be alerted more loudly to certain elog/ereport WARNINGs. pg_regress wouldn't miss any WARNINGs that were not expected, but the TAP tests could. Here we define BUG_WARNING, which is the same as WARNING on production builds, but gets promoted to ERROR in assert-enabled builds. The idea is that WARNINGs that we really don't expect to get can be adjusted to use BUG_WARNING instead. This also adjusts a select few such elog calls to demonstrate. Patch-grade: REQUEST FOR COMMENTS ONLY --- src/backend/utils/mmgr/aset.c | 18 +- src/backend/utils/mmgr/bump.c | 6 +- src/backend/utils/mmgr/generation.c | 16 +- src/backend/utils/mmgr/slab.c | 18 +- src/backend/utils/resowner/resowner.c | 2 +- src/include/utils/elog.h | 12 ++ .../expected/test_resowner_1.out | 192 ++++++++++++++++++ .../expected/test_resowner_2.out | 192 ++++++++++++++++++ 8 files changed, 426 insertions(+), 30 deletions(-) create mode 100644 src/test/modules/test_resowner/expected/test_resowner_1.out create mode 100644 src/test/modules/test_resowner/expected/test_resowner_2.out diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c index 6a9ea367107..626941a79f1 100644 --- a/src/backend/utils/mmgr/aset.c +++ b/src/backend/utils/mmgr/aset.c @@ -1706,7 +1706,7 @@ AllocSetCheck(MemoryContext context) if (!blk_used) { if (!IsKeeperBlock(set, block)) - elog(WARNING, "problem in alloc set %s: empty block %p", + elog(BUG_WARNING, "problem in alloc set %s: empty block %p", name, block); } @@ -1717,7 +1717,7 @@ AllocSetCheck(MemoryContext context) block->prev != prevblock || block->freeptr < bpoz || block->freeptr > block->endptr) - elog(WARNING, "problem in alloc set %s: corrupt header in block %p", + elog(BUG_WARNING, "problem in alloc set %s: corrupt header in block %p", name, block); /* @@ -1739,7 +1739,7 @@ AllocSetCheck(MemoryContext context) /* make sure this chunk consumes the entire block */ if (chsize + ALLOC_CHUNKHDRSZ != blk_used) - elog(WARNING, "problem in alloc set %s: bad single-chunk %p in block %p", + elog(BUG_WARNING, "problem in alloc set %s: bad single-chunk %p in block %p", name, chunk, block); } else @@ -1747,7 +1747,7 @@ AllocSetCheck(MemoryContext context) int fidx = MemoryChunkGetValue(chunk); if (!FreeListIdxIsValid(fidx)) - elog(WARNING, "problem in alloc set %s: bad chunk size for chunk %p in block %p", + elog(BUG_WARNING, "problem in alloc set %s: bad chunk size for chunk %p in block %p", name, chunk, block); chsize = GetChunkSizeFromFreeListIdx(fidx); /* aligned chunk size */ @@ -1757,7 +1757,7 @@ AllocSetCheck(MemoryContext context) * block. */ if (block != MemoryChunkGetBlock(chunk)) - elog(WARNING, "problem in alloc set %s: bad block offset for chunk %p in block %p", + elog(BUG_WARNING, "problem in alloc set %s: bad block offset for chunk %p in block %p", name, chunk, block); } dsize = chunk->requested_size; /* real data */ @@ -1769,7 +1769,7 @@ AllocSetCheck(MemoryContext context) /* chsize must not be smaller than the first freelist's size */ if (chsize < (1 << ALLOC_MINBITS)) - elog(WARNING, "problem in alloc set %s: bad size %zu for chunk %p in block %p", + elog(BUG_WARNING, "problem in alloc set %s: bad size %zu for chunk %p in block %p", name, chsize, chunk, block); /* @@ -1777,7 +1777,7 @@ AllocSetCheck(MemoryContext context) */ if (dsize != InvalidAllocSize && dsize < chsize && !sentinel_ok(chunk, ALLOC_CHUNKHDRSZ + dsize)) - elog(WARNING, "problem in alloc set %s: detected write past chunk end in block %p, chunk %p", + elog(BUG_WARNING, "problem in alloc set %s: detected write past chunk end in block %p, chunk %p", name, block, chunk); /* if chunk is allocated, disallow access to the chunk header */ @@ -1791,11 +1791,11 @@ AllocSetCheck(MemoryContext context) } if ((blk_data + (nchunks * ALLOC_CHUNKHDRSZ)) != blk_used) - elog(WARNING, "problem in alloc set %s: found inconsistent memory block %p", + elog(BUG_WARNING, "problem in alloc set %s: found inconsistent memory block %p", name, block); if (has_external_chunk && nchunks > 1) - elog(WARNING, "problem in alloc set %s: external chunk on non-dedicated block %p", + elog(BUG_WARNING, "problem in alloc set %s: external chunk on non-dedicated block %p", name, block); } diff --git a/src/backend/utils/mmgr/bump.c b/src/backend/utils/mmgr/bump.c index 9bb579935db..8f46be180fe 100644 --- a/src/backend/utils/mmgr/bump.c +++ b/src/backend/utils/mmgr/bump.c @@ -786,7 +786,7 @@ BumpCheck(MemoryContext context) /* check block belongs to the correct context */ if (block->context != bump) - elog(WARNING, "problem in Bump %s: bogus context link in block %p", + elog(BUG_WARNING, "problem in Bump %s: bogus context link in block %p", name, block); /* now walk through the chunks and count them */ @@ -821,12 +821,12 @@ BumpCheck(MemoryContext context) /* chunks have both block and context pointers, so check both */ if (chunkblock != block) - elog(WARNING, "problem in Bump %s: bogus block link in block %p, chunk %p", + elog(BUG_WARNING, "problem in Bump %s: bogus block link in block %p, chunk %p", name, block, chunk); } if (has_external_chunk && nchunks > 1) - elog(WARNING, "problem in Bump %s: external chunk on non-dedicated block %p", + elog(BUG_WARNING, "problem in Bump %s: external chunk on non-dedicated block %p", name, block); } diff --git a/src/backend/utils/mmgr/generation.c b/src/backend/utils/mmgr/generation.c index 609c9bdc9a6..c17da92a25c 100644 --- a/src/backend/utils/mmgr/generation.c +++ b/src/backend/utils/mmgr/generation.c @@ -1152,12 +1152,12 @@ GenerationCheck(MemoryContext context) * might completely empty if it's the freeblock. */ if (block->nfree > block->nchunks) - elog(WARNING, "problem in Generation %s: number of free chunks %d in block %p exceeds %d allocated", + elog(BUG_WARNING, "problem in Generation %s: number of free chunks %d in block %p exceeds %d allocated", name, block->nfree, block, block->nchunks); /* check block belongs to the correct context */ if (block->context != gen) - elog(WARNING, "problem in Generation %s: bogus context link in block %p", + elog(BUG_WARNING, "problem in Generation %s: bogus context link in block %p", name, block); /* Now walk through the chunks and count them. */ @@ -1193,7 +1193,7 @@ GenerationCheck(MemoryContext context) /* chunks have both block and context pointers, so check both */ if (chunkblock != block) - elog(WARNING, "problem in Generation %s: bogus block link in block %p, chunk %p", + elog(BUG_WARNING, "problem in Generation %s: bogus block link in block %p, chunk %p", name, block, chunk); @@ -1203,13 +1203,13 @@ GenerationCheck(MemoryContext context) /* now make sure the chunk size is correct */ if (chunksize < chunk->requested_size || chunksize != MAXALIGN(chunksize)) - elog(WARNING, "problem in Generation %s: bogus chunk size in block %p, chunk %p", + elog(BUG_WARNING, "problem in Generation %s: bogus chunk size in block %p, chunk %p", name, block, chunk); /* check sentinel */ Assert(chunk->requested_size < chunksize); if (!sentinel_ok(chunk, Generation_CHUNKHDRSZ + chunk->requested_size)) - elog(WARNING, "problem in Generation %s: detected write past chunk end in block %p, chunk %p", + elog(BUG_WARNING, "problem in Generation %s: detected write past chunk end in block %p, chunk %p", name, block, chunk); } else @@ -1225,15 +1225,15 @@ GenerationCheck(MemoryContext context) * (as tracked in the block header). */ if (nchunks != block->nchunks) - elog(WARNING, "problem in Generation %s: number of allocated chunks %d in block %p does not match header %d", + elog(BUG_WARNING, "problem in Generation %s: number of allocated chunks %d in block %p does not match header %d", name, nchunks, block, block->nchunks); if (nfree != block->nfree) - elog(WARNING, "problem in Generation %s: number of free chunks %d in block %p does not match header %d", + elog(BUG_WARNING, "problem in Generation %s: number of free chunks %d in block %p does not match header %d", name, nfree, block, block->nfree); if (has_external_chunk && nchunks > 1) - elog(WARNING, "problem in Generation %s: external chunk on non-dedicated block %p", + elog(BUG_WARNING, "problem in Generation %s: external chunk on non-dedicated block %p", name, block); } diff --git a/src/backend/utils/mmgr/slab.c b/src/backend/utils/mmgr/slab.c index 2ad325547fd..cf830432908 100644 --- a/src/backend/utils/mmgr/slab.c +++ b/src/backend/utils/mmgr/slab.c @@ -1054,7 +1054,7 @@ SlabCheck(MemoryContext context) SlabBlock *block = dlist_container(SlabBlock, node, iter.cur); if (block->nfree != slab->chunksPerBlock) - elog(WARNING, "problem in slab %s: empty block %p should have %d free chunks but has %d chunks free", + elog(BUG_WARNING, "problem in slab %s: empty block %p should have %d free chunks but has %d chunks free", name, block, slab->chunksPerBlock, block->nfree); } @@ -1075,17 +1075,17 @@ SlabCheck(MemoryContext context) * matches the position in the blocklist. */ if (SlabBlocklistIndex(slab, block->nfree) != i) - elog(WARNING, "problem in slab %s: block %p is on blocklist %d but should be on blocklist %d", + elog(BUG_WARNING, "problem in slab %s: block %p is on blocklist %d but should be on blocklist %d", name, block, i, SlabBlocklistIndex(slab, block->nfree)); /* make sure the block is not empty */ if (block->nfree >= slab->chunksPerBlock) - elog(WARNING, "problem in slab %s: empty block %p incorrectly stored on blocklist element %d", + elog(BUG_WARNING, "problem in slab %s: empty block %p incorrectly stored on blocklist element %d", name, block, i); /* make sure the slab pointer correctly points to this context */ if (block->slab != slab) - elog(WARNING, "problem in slab %s: bogus slab link in block %p", + elog(BUG_WARNING, "problem in slab %s: bogus slab link in block %p", name, block); /* reset the array of free chunks for this block */ @@ -1105,7 +1105,7 @@ SlabCheck(MemoryContext context) if (cur_chunk < SlabBlockGetChunk(slab, block, 0) || cur_chunk > SlabBlockGetChunk(slab, block, slab->chunksPerBlock - 1) || SlabChunkMod(slab, block, cur_chunk) != 0) - elog(WARNING, "problem in slab %s: bogus free list link %p in block %p", + elog(BUG_WARNING, "problem in slab %s: bogus free list link %p in block %p", name, cur_chunk, block); /* count the chunk and mark it free on the free chunk array */ @@ -1120,7 +1120,7 @@ SlabCheck(MemoryContext context) /* check that the unused pointer matches what nunused claims */ if (SlabBlockGetChunk(slab, block, slab->chunksPerBlock - block->nunused) != block->unused) - elog(WARNING, "problem in slab %s: mismatch detected between nunused chunks and unused pointer in block %p", + elog(BUG_WARNING, "problem in slab %s: mismatch detected between nunused chunks and unused pointer in block %p", name, block); /* @@ -1162,13 +1162,13 @@ SlabCheck(MemoryContext context) * the block */ if (chunkblock != block) - elog(WARNING, "problem in slab %s: bogus block link in block %p, chunk %p", + elog(BUG_WARNING, "problem in slab %s: bogus block link in block %p, chunk %p", name, block, chunk); /* check the sentinel byte is intact */ Assert(slab->chunkSize < (slab->fullChunkSize - Slab_CHUNKHDRSZ)); if (!sentinel_ok(chunk, Slab_CHUNKHDRSZ + slab->chunkSize)) - elog(WARNING, "problem in slab %s: detected write past chunk end in block %p, chunk %p", + elog(BUG_WARNING, "problem in slab %s: detected write past chunk end in block %p, chunk %p", name, block, chunk); } } @@ -1178,7 +1178,7 @@ SlabCheck(MemoryContext context) * in the block header). */ if (nfree != block->nfree) - elog(WARNING, "problem in slab %s: nfree in block %p is %d but %d chunk were found as free", + elog(BUG_WARNING, "problem in slab %s: nfree in block %p is %d but %d chunk were found as free", name, block, block->nfree, nfree); nblocks++; diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c index ac413d54837..8dac4a91019 100644 --- a/src/backend/utils/resowner/resowner.c +++ b/src/backend/utils/resowner/resowner.c @@ -392,7 +392,7 @@ ResourceOwnerReleaseAll(ResourceOwner owner, ResourceReleasePhase phase, res_str = kind->DebugPrint ? kind->DebugPrint(value) : psprintf("%s %p", kind->name, DatumGetPointer(value)); - elog(WARNING, "resource was not closed: %s", res_str); + elog(BUG_WARNING, "resource was not closed: %s", res_str); pfree(res_str); } diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index 6ae376ba001..6356f2093ba 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -57,6 +57,18 @@ struct Node; #define FATAL_CLIENT_ONLY 23 /* fatal version of WARNING_CLIENT_ONLY */ #define PANIC 24 /* take down the other backends with me */ +/* + * Some elog/ereports that we report a WARNING for are likely to be caused by + * buggy code. These may go unnoticed by some of our test suites (e.g. TAP + * tests). Here we define a macro which can be used in selected places where + * we don't want the given WARNING to not be noticed. + */ +#ifdef USE_ASSERT_CHECKING +#define BUG_WARNING ERROR +#else +#define BUG_WARNING WARNING +#endif + /* * NOTE: the alternate names PGWARNING and PGERROR are useful for dealing * with third-party headers that make other definitions of WARNING and/or diff --git a/src/test/modules/test_resowner/expected/test_resowner_1.out b/src/test/modules/test_resowner/expected/test_resowner_1.out new file mode 100644 index 00000000000..c11255c83c8 --- /dev/null +++ b/src/test/modules/test_resowner/expected/test_resowner_1.out @@ -0,0 +1,192 @@ +CREATE EXTENSION test_resowner; +-- This is small enough that everything fits in the small array +SELECT test_resowner_priorities(2, 3); +NOTICE: releasing resources before locks +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing locks +NOTICE: releasing resources after locks +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 2 + test_resowner_priorities +-------------------------- + +(1 row) + +-- Same test with more resources, to exercise the hash table +SELECT test_resowner_priorities(2, 32); +NOTICE: releasing resources before locks +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing locks +NOTICE: releasing resources after locks +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 + test_resowner_priorities +-------------------------- + +(1 row) + +-- Basic test with lots more resources, to test extending the hash table +SELECT test_resowner_many( + 3, -- # of different resource kinds + 100000, -- before-locks resources to remember + 500, -- before-locks resources to forget + 100000, -- after-locks resources to remember + 500 -- after-locks resources to forget +); +NOTICE: remembering 100000 before-locks resources +NOTICE: remembering 100000 after-locks resources +NOTICE: forgetting 500 before-locks resources +NOTICE: forgetting 500 after-locks resources +NOTICE: releasing resources before locks +NOTICE: releasing locks +NOTICE: releasing resources after locks + test_resowner_many +-------------------- + +(1 row) + +-- Test resource leak warning +SELECT test_resowner_leak(); +NOTICE: releasing string: my string +ERROR: resource was not closed: test string "my string" +-- Negative tests, using a resource owner after release-phase has started. +set client_min_messages='warning'; -- order between ERROR and NOTICE varies +SELECT test_resowner_remember_between_phases(); +ERROR: ResourceOwnerEnlarge called after release started +SELECT test_resowner_forget_between_phases(); +ERROR: ResourceOwnerForget called for test resource after release started +reset client_min_messages; diff --git a/src/test/modules/test_resowner/expected/test_resowner_2.out b/src/test/modules/test_resowner/expected/test_resowner_2.out new file mode 100644 index 00000000000..e091713b04a --- /dev/null +++ b/src/test/modules/test_resowner/expected/test_resowner_2.out @@ -0,0 +1,192 @@ +CREATE EXTENSION test_resowner; +-- This is small enough that everything fits in the small array +SELECT test_resowner_priorities(2, 3); +NOTICE: releasing resources before locks +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing locks +NOTICE: releasing resources after locks +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 2 + test_resowner_priorities +-------------------------- + +(1 row) + +-- Same test with more resources, to exercise the hash table +SELECT test_resowner_priorities(2, 32); +NOTICE: releasing resources before locks +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 1 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: child before locks priority 2 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 1 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing string: parent before locks priority 2 +NOTICE: releasing locks +NOTICE: releasing resources after locks +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 1 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: child after locks priority 2 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 1 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 +NOTICE: releasing string: parent after locks priority 2 + test_resowner_priorities +-------------------------- + +(1 row) + +-- Basic test with lots more resources, to test extending the hash table +SELECT test_resowner_many( + 3, -- # of different resource kinds + 100000, -- before-locks resources to remember + 500, -- before-locks resources to forget + 100000, -- after-locks resources to remember + 500 -- after-locks resources to forget +); +NOTICE: remembering 100000 before-locks resources +NOTICE: remembering 100000 after-locks resources +NOTICE: forgetting 500 before-locks resources +NOTICE: forgetting 500 after-locks resources +NOTICE: releasing resources before locks +NOTICE: releasing locks +NOTICE: releasing resources after locks + test_resowner_many +-------------------- + +(1 row) + +-- Test resource leak warning +SELECT test_resowner_leak(); +ERROR: resource was not closed: test string "my string" +NOTICE: releasing string: my string +-- Negative tests, using a resource owner after release-phase has started. +set client_min_messages='warning'; -- order between ERROR and NOTICE varies +SELECT test_resowner_remember_between_phases(); +ERROR: ResourceOwnerEnlarge called after release started +SELECT test_resowner_forget_between_phases(); +ERROR: ResourceOwnerForget called for test resource after release started +reset client_min_messages; -- 2.53.0