From bed5806c3adb3a3da3497f61ccf7668867ffb85a Mon Sep 17 00:00:00 2001
From: "yizhi.fzh" <yizhi.fzh@alibaba-inc.com>
Date: Mon, 22 Jan 2024 07:14:29 +0800
Subject: [PATCH v8 3/3] bypass SpinLock checking in SIGQUIT signal hander

When a process receives a SIGQUIT signal, it indicates the system has a
crash time. It's possible that the process is just holding a Spin lock.
By our current rules, this process will PANIC with a misuse of spinlock
reason which is pretty prone to misunderstanding. so we need to bypass
the spin lock holding checking in this case. It is safe since the
overall system will be restarted.
---
 src/backend/storage/lmgr/spin.c |  6 ++++++
 src/backend/tcop/postgres.c     | 12 ++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/src/backend/storage/lmgr/spin.c b/src/backend/storage/lmgr/spin.c
index 08cc6da5d9..006975bafa 100644
--- a/src/backend/storage/lmgr/spin.c
+++ b/src/backend/storage/lmgr/spin.c
@@ -26,6 +26,7 @@
 #include "storage/shmem.h"
 #include "storage/spin.h"
 
+extern PGDLLIMPORT volatile bool quickDieInProgress;
 
 #ifndef HAVE_SPINLOCKS
 
@@ -186,6 +187,11 @@ void
 VerifyNoSpinLocksHeld(void)
 {
 #ifdef USE_ASSERT_CHECKING
+	/*
+	 * In the quickdie progress, it's OK to ignore the spin lock checking.
+	 */
+	if (quickDieInProgress)
+		return;
 	if (last_spin_lock_file != NULL)
 		elog(PANIC, "A spin lock has been held at %s:%d",
 			 last_spin_lock_file, last_spin_lock_lineno);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 1a34bd3715..11103835a6 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -102,6 +102,8 @@ int			PostAuthDelay = 0;
 /* Time between checks that the client is still connected. */
 int			client_connection_check_interval = 0;
 
+volatile bool quickDieInProgress = false;
+
 /* ----------------
  *		private typedefs etc
  * ----------------
@@ -2876,6 +2878,16 @@ quickdie(SIGNAL_ARGS)
 	sigaddset(&BlockSig, SIGQUIT);	/* prevent nested calls */
 	sigprocmask(SIG_SETMASK, &BlockSig, NULL);
 
+	/*
+	 * It's likely to check the BlockSig to know if it is doing a quickdie
+	 * with sigismember, but it is too expensive in test, so introduce
+	 * quickDieInProgress to avoid that.
+	 *
+	 * When this is set, we are sure this backend will die very soon, so no
+	 * need to reset it back to false anytime.
+	 */
+	quickDieInProgress = true;
+
 	/*
 	 * Prevent interrupts while exiting; though we just blocked signals that
 	 * would queue new interrupts, one may have been pending.  We don't want a
-- 
2.34.1

