Hello, Nathan and Michael!

I believe I’ve identified the root cause of the issue. It appears to be
related to the GetNamedDSMSegment and injection_points module.

Here’s how it happens:

* A backend attaches (even locally!) to an injection point, which might get
triggered during resource release (ResourceOwnerRelease).
* Another backend attempts to release the same resource (e.g., by aborting
a transaction) and triggers the injection point.
* This leads to a call to GetNamedDSMSegment, as it’s the first time this
backend interacts with injection points.
* Consequently, an assertion failure occurs in ResourceOwnerEnlarge because
the backend is in the process of releasing all resources.

I’ve attached a reproducer—this version is much simpler for debugging.

So, it looks like we need to provide some option to guarantee
GetNamedDSMSegment called for injection points module.

Any other ideas?

Best regards,
Mikhail.

[0]:
https://github.com/postgres/postgres/commit/8b2bcf3f287c79eaebf724cba57e5ff664b01e06
From e56b6de29aea01916d35d22e9a59241a04202b37 Mon Sep 17 00:00:00 2001
From: nkey <michail.nikol...@gmail.com>
Date: Wed, 27 Nov 2024 02:10:17 +0100
Subject: [PATCH v2] Test to reproduce issue with crash caused by passing throw
 injection points during transaction aborting (caused by call to
 injection_init_shmem).

---
 src/backend/utils/time/snapmgr.c              |  2 +
 src/test/modules/injection_points/Makefile    |  2 +-
 .../injection_points/expected/crash.out       | 26 ++++++++++
 src/test/modules/injection_points/meson.build |  1 +
 .../modules/injection_points/specs/crash.spec | 47 +++++++++++++++++++
 5 files changed, 77 insertions(+), 1 deletion(-)
 create mode 100644 src/test/modules/injection_points/expected/crash.out
 create mode 100644 src/test/modules/injection_points/specs/crash.spec

diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
index 7d2b34d4f20..3a7357a050d 100644
--- a/src/backend/utils/time/snapmgr.c
+++ b/src/backend/utils/time/snapmgr.c
@@ -64,6 +64,7 @@
 #include "utils/resowner.h"
 #include "utils/snapmgr.h"
 #include "utils/syscache.h"
+#include "utils/injection_point.h"
 
 
 /*
@@ -426,6 +427,7 @@ InvalidateCatalogSnapshot(void)
                pairingheap_remove(&RegisteredSnapshots, 
&CatalogSnapshot->ph_node);
                CatalogSnapshot = NULL;
                SnapshotResetXmin();
+               INJECTION_POINT("invalidate_catalog_snapshot_end");
        }
 }
 
diff --git a/src/test/modules/injection_points/Makefile 
b/src/test/modules/injection_points/Makefile
index 0753a9df58c..da8930ea49f 100644
--- a/src/test/modules/injection_points/Makefile
+++ b/src/test/modules/injection_points/Makefile
@@ -13,7 +13,7 @@ PGFILEDESC = "injection_points - facility for injection 
points"
 REGRESS = injection_points reindex_conc
 REGRESS_OPTS = --dlpath=$(top_builddir)/src/test/regress
 
-ISOLATION = basic inplace
+ISOLATION = basic crash inplace
 
 TAP_TESTS = 1
 
diff --git a/src/test/modules/injection_points/expected/crash.out 
b/src/test/modules/injection_points/expected/crash.out
new file mode 100644
index 00000000000..7d7f298c786
--- /dev/null
+++ b/src/test/modules/injection_points/expected/crash.out
@@ -0,0 +1,26 @@
+Parsed test spec with 4 sessions
+
+starting permutation: s4_attach_locally wx1 rxwy2 c1 ry3 c2 c3
+injection_points_set_local
+--------------------------
+                          
+(1 row)
+
+step s4_attach_locally: SELECT 
injection_points_attach('invalidate_catalog_snapshot_end', 'wait');
+injection_points_attach
+-----------------------
+                       
+(1 row)
+
+step wx1: update D1 set id = id + 1;
+step rxwy2: update D2 set id = (select id+1 from D1);
+step c1: COMMIT;
+step ry3: select id from D2;
+id
+--
+ 1
+(1 row)
+
+step c2: COMMIT;
+ERROR:  could not serialize access due to read/write dependencies among 
transactions
+step c3: COMMIT;
diff --git a/src/test/modules/injection_points/meson.build 
b/src/test/modules/injection_points/meson.build
index 58f19001157..6079187dd57 100644
--- a/src/test/modules/injection_points/meson.build
+++ b/src/test/modules/injection_points/meson.build
@@ -43,6 +43,7 @@ tests += {
   'isolation': {
     'specs': [
       'basic',
+      'crash',
       'inplace',
     ],
   },
diff --git a/src/test/modules/injection_points/specs/crash.spec 
b/src/test/modules/injection_points/specs/crash.spec
new file mode 100644
index 00000000000..55e6a5434ab
--- /dev/null
+++ b/src/test/modules/injection_points/specs/crash.spec
@@ -0,0 +1,47 @@
+setup
+{
+ create table D1 (id int primary key not null);
+ create table D2 (id int primary key not null);
+ insert into D1 values (1);
+ insert into D2 values (1);
+
+ CREATE EXTENSION injection_points;
+}
+
+teardown
+{
+ DROP TABLE D1, D2;
+ DROP EXTENSION injection_points;
+}
+
+session s1
+setup          { BEGIN ISOLATION LEVEL SERIALIZABLE;}
+step wx1       { update D1 set id = id + 1; }
+step c1                { COMMIT; }
+
+session s2
+setup          {
+       BEGIN ISOLATION LEVEL SERIALIZABLE;
+}
+step rxwy2     { update D2 set id = (select id+1 from D1); }
+step c2                { COMMIT; }
+
+session s3
+setup          { BEGIN ISOLATION LEVEL SERIALIZABLE; }
+step ry3       { select id from D2; }
+step c3                { COMMIT; }
+
+session s4
+setup  {
+       SELECT injection_points_set_local();
+}
+step s4_attach_locally { SELECT 
injection_points_attach('invalidate_catalog_snapshot_end', 'wait'); }
+
+permutation
+       s4_attach_locally
+       wx1
+       rxwy2
+       c1
+       ry3
+       c2
+       c3
\ No newline at end of file
-- 
2.43.0

Reply via email to