@@ -86,6 +86,8 @@ static LOCALLOCK *lockAwaited = NULL;
86
86
87
87
static DeadLockState deadlock_state = DS_NOT_YET_CHECKED ;
88
88
89
+ static bool inside_deadlock_check = false;
90
+
89
91
/* Is a deadlock check pending? */
90
92
static volatile sig_atomic_t got_deadlock_timeout ;
91
93
@@ -755,6 +757,14 @@ ProcReleaseLocks(bool isCommit)
755
757
{
756
758
if (!MyProc )
757
759
return ;
760
+
761
+ /* Release deadlock detection flag is backend was interrupted inside deadlock check */
762
+ if (inside_deadlock_check )
763
+ {
764
+ pg_atomic_clear_flag (& ProcGlobal -> activeDeadlockCheck );
765
+ inside_deadlock_check = false;
766
+ }
767
+
758
768
/* If waiting, get off wait queue (should only be needed after error) */
759
769
LockErrorCleanup ();
760
770
/* Release standard locks, including session-level if aborting */
@@ -1662,6 +1672,14 @@ CheckDeadLock(void)
1662
1672
if (!pg_atomic_test_set_flag (& ProcGlobal -> activeDeadlockCheck ))
1663
1673
return ;
1664
1674
1675
+ /*
1676
+ * Ensure that only one backend is checking for deadlock.
1677
+ * Otherwise under high load cascade of deadlock timeout expirations can cause stuck of Postgres.
1678
+ */
1679
+ if (!pg_atomic_test_set_flag (& ProcGlobal -> activeDeadlockCheck ))
1680
+ return ;
1681
+ inside_deadlock_check = true;
1682
+
1665
1683
/*
1666
1684
* Acquire exclusive lock on the entire shared lock data structures. Must
1667
1685
* grab LWLocks in partition-number order to avoid LWLock deadlock.
@@ -1739,6 +1757,7 @@ CheckDeadLock(void)
1739
1757
LWLockRelease (LockHashPartitionLockByIndex (i ));
1740
1758
1741
1759
pg_atomic_clear_flag (& ProcGlobal -> activeDeadlockCheck );
1760
+ inside_deadlock_check = false;
1742
1761
}
1743
1762
1744
1763
/*
0 commit comments