summaryrefslogtreecommitdiff
path: root/src/backend/storage
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage')
-rw-r--r--src/backend/storage/ipc/standby.c23
-rw-r--r--src/backend/storage/lmgr/lock.c7
-rw-r--r--src/backend/storage/lmgr/proc.c9
3 files changed, 21 insertions, 18 deletions
diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c
index 75b5ab458a8..bf92d259950 100644
--- a/src/backend/storage/ipc/standby.c
+++ b/src/backend/storage/ipc/standby.c
@@ -459,24 +459,25 @@ SendRecoveryConflictWithBufferPin(ProcSignalReason reason)
/*
* In Hot Standby perform early deadlock detection. We abort the lock
- * wait if are about to sleep while holding the buffer pin that Startup
- * process is waiting for. The deadlock occurs because we can only be
- * waiting behind an AccessExclusiveLock, which can only clear when a
- * transaction completion record is replayed, which can only occur when
- * Startup process is not waiting. So if Startup process is waiting we
- * never will clear that lock, so if we wait we cause deadlock. If we
- * are the Startup process then no need to check for deadlocks.
+ * wait if we are about to sleep while holding the buffer pin that Startup
+ * process is waiting for.
+ *
+ * Note: this code is pessimistic, because there is no way for it to
+ * determine whether an actual deadlock condition is present: the lock we
+ * need to wait for might be unrelated to any held by the Startup process.
+ * Sooner or later, this mechanism should get ripped out in favor of somehow
+ * accounting for buffer locks in DeadLockCheck(). However, errors here
+ * seem to be very low-probability in practice, so for now it's not worth
+ * the trouble.
*/
void
-CheckRecoveryConflictDeadlock(LWLockId partitionLock)
+CheckRecoveryConflictDeadlock(void)
{
- Assert(!InRecovery);
+ Assert(!InRecovery); /* do not call in Startup process */
if (!HoldingBufferPinThatDelaysRecovery())
return;
- LWLockRelease(partitionLock);
-
/*
* Error message should match ProcessInterrupts() but we avoid calling
* that because we aren't handling an interrupt at this point. Note that
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index e3ad3199c4d..e3e1dd249f2 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -832,13 +832,6 @@ LockAcquireExtended(const LOCKTAG *locktag,
}
/*
- * In Hot Standby perform early deadlock detection in normal backends.
- * If deadlock found we release partition lock but do not return.
- */
- if (RecoveryInProgress() && !InRecovery)
- CheckRecoveryConflictDeadlock(partitionLock);
-
- /*
* Set bitmask of locks this process already holds on this object.
*/
MyProc->heldLocks = proclock->holdMask;
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 78d1fd29343..7da4337a156 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -940,6 +940,15 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
*/
LWLockRelease(partitionLock);
+ /*
+ * Also, now that we will successfully clean up after an ereport, it's
+ * safe to check to see if there's a buffer pin deadlock against the
+ * Startup process. Of course, that's only necessary if we're doing
+ * Hot Standby and are not the Startup process ourselves.
+ */
+ if (RecoveryInProgress() && !InRecovery)
+ CheckRecoveryConflictDeadlock();
+
/* Reset deadlock_state before enabling the signal handler */
deadlock_state = DS_NOT_YET_CHECKED;