Hello Michael and Matthias,
Could you please look at other similar anomalies I have discovered?:
(Assuming the attached OOM injection patch applied.)
1) An issue in generate_partition_qual():
--- a/src/backend/utils/cache/partcache.c
+++ b/src/backend/utils/cache/partcache.c
@@ -419,3 +419,5 @@ generate_partition_qual(Relation rel)
oldcxt = MemoryContextSwitchTo(rel->rd_partcheckcxt);
+oom_prob = 0.1;
rel->rd_partcheck = copyObject(result);
+oom_prob = 0;
MemoryContextSwitchTo(oldcxt);
for i in {1..100}; do
echo "
CREATE TABLE t1(a INT PRIMARY KEY) PARTITION BY RANGE (a);
CREATE TABLE t1p1 PARTITION OF t1 FOR VALUES FROM (1) TO (2) PARTITION BY LIST
(a);
CREATE TABLE t2 (a INT, CONSTRAINT fkey FOREIGN KEY(a) REFERENCES t1(a));
INSERT INTO t2 VALUES (1);
INSERT INTO t2 VALUES (1);
DROP TABLE t1, t2 CASCADE;
" | psql
grep 'TRAP' server.log && break;
done
triggers
TRAP: failed Assert("cache->cc_tupdesc != NULL"), File: "catcache.c", Line:
1112, PID: 43932
2) lookup_type_cache():
--- a/src/backend/utils/cache/typcache.c
+++ b/src/backend/utils/cache/typcache.c
@@ -463,8 +463,10 @@ lookup_type_cache(Oid type_id, int flags)
in_progress_list[in_progress_offset] = type_id;
+oom_prob = 0.1;
/* Try to look up an existing entry */
typentry = (TypeCacheEntry *) hash_search(TypeCacheHash,
&type_id,
HASH_FIND, NULL);
+oom_prob = 0;
if (typentry == NULL)
{
for i in {1..10}; do
echo "
CREATE TABLE t(a int);
\c
SELECT * FROM t ORDER BY a;
DROP TABLE t;
" | psql
grep 'TRAP' server.log && break;
done
triggers
TRAP: failed Assert("cache->cc_tupdesc != NULL"), File: "catcache.c", Line:
1112, PID: 43932
3) pgstat_prep_pending_entry() / pgstat_write_statsfiles():
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -1333,3 +1333,5 @@ pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid,
uint64 objid, bool *creat
+oom_prob = 0.005;
entry_ref->pending = MemoryContextAllocZero(pgStatPendingContext,
entrysize);
+oom_prob = 0;
dlist_push_tail(&pgStatPending, &entry_ref->pending_node);
for i in {1..100}; do
pg_ctl -l server.log start
echo "
CREATE TABLE t (a int);
ALTER TABLE t SET (parallel_workers = 20);
SET parallel_setup_cost = 0;
SELECT SUM(a) FROM t;
DROP TABLE t;
" | psql
pg_ctl -l server.log stop
grep 'TRAP' server.log && break;
done
triggers
TRAP: failed Assert("!ps->dropped"), File: "pgstat.c", Line: 1730, PID: 844901
maybe this Assert can be removed, because there is no corresponding
assert in pgstat_build_snapshot(), but I saw also:
TRAP: failed Assert("rel->pgstat_info->relation == NULL"), File:
"pgstat_relation.c", Line: 142, PID: 157820
TRAP: failed Assert("ent->entry_ref != NULL"), File: "pgstat_shmem.c", Line:
827, PID: 190431
4) make_new_heap():
--- a/src/backend/commands/repack.c
+++ b/src/backend/commands/repack.c
@@ -1255,3 +1255,5 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace, Oid
NewAccessMethod,
*/
+oom_prob = 0.01;
CommandCounterIncrement();
+oom_prob = 0;
for i in {1..100}; do
echo "
CREATE TABLE t1(i int PRIMARY KEY);
CLUSTER t1 USING t1_pkey;
CREATE TABLE t2(i int PRIMARY KEY);
CLUSTER t2 USING t2_pkey;
DROP TABLE t2;
DROP TABLE t1;
" | psql
grep 'TRAP' server.log && break;
done
triggers:
TRAP: failed Assert("ItemIdIsNormal(lp)"), File: "heapam.c", Line: 2813, PID:
943626
also:
ERROR: attempted to delete invisible tuple
(similar to [1], which can also be triggered with OOM inside
CommandCounterIncrement(), but this one is even more interesting, IMO)
[1]
https://www.postgresql.org/message-id/21363eb7-606c-468d-88f4-c14162ddafc8%40gmail.com
Best regards,
Alexanderdiff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 6a9ea367107..af4d55f9b4c 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -51,6 +51,7 @@
#include "utils/memutils.h"
#include "utils/memutils_internal.h"
#include "utils/memutils_memorychunk.h"
+#include "common/pg_prng.h"
/*--------------------
* Chunk freelist k holds chunks of size 1 << (k + ALLOC_MINBITS),
@@ -946,6 +947,7 @@ AllocSetAllocFromNewBlock(MemoryContext context, Size size, int flags,
while (blksize < required_size)
blksize <<= 1;
+if (pg_prng_double(&pg_global_prng_state) < oom_prob) { oom_prob = 0; return MemoryContextAllocationFailure(context, size, flags); }
/* Try to allocate it */
block = (AllocBlock) malloc(blksize);
@@ -1023,6 +1025,7 @@ AllocSetAlloc(MemoryContext context, Size size, int flags)
/* due to the keeper block set->blocks should never be NULL */
Assert(set->blocks != NULL);
+if (pg_prng_double(&pg_global_prng_state) < oom_prob) { oom_prob = 0; return MemoryContextAllocationFailure(context, size, flags); }
/*
* If requested size exceeds maximum for chunks we hand the request off to
* AllocSetAllocLarge().
diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c
index 930fc457328..af050ed870d 100644
--- a/src/backend/utils/mmgr/mcxt.c
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -46,6 +46,7 @@
#include "utils/memutils_internal.h"
#include "utils/memutils_memorychunk.h"
+double oom_prob = 0;
static void BogusFree(void *pointer);
static void *BogusRealloc(void *pointer, Size size, int flags);
diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h
index 0e934158b60..90033ddc5a3 100644
--- a/src/include/utils/palloc.h
+++ b/src/include/utils/palloc.h
@@ -163,5 +163,6 @@ extern char *pchomp(const char *in);
/* sprintf into a palloc'd buffer --- these are in psprintf.c */
extern char *psprintf(const char *fmt, ...) pg_attribute_printf(1, 2);
extern size_t pvsnprintf(char *buf, size_t len, const char *fmt, va_list args) pg_attribute_printf(3, 0);
+extern double oom_prob;
#endif /* PALLOC_H */