Skip to content

Commit e419d86

Browse files
committed
Back-patch deadlock recovery fix into 7.1 tree, in case someone needs it.
1 parent 8c78169 commit e419d86

File tree

1 file changed

+27
-9
lines changed
  • src/backend/storage/lmgr

1 file changed

+27
-9
lines changed

src/backend/storage/lmgr/proc.c

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.100 2001/03/22 06:16:17 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.100.2.1 2001/09/12 17:14:39 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -516,16 +516,14 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
516516
SPINLOCK spinlock = lockctl->masterLock;
517517
PROC_QUEUE *waitQueue = &(lock->waitProcs);
518518
int myHeldLocks = MyProc->heldLocks;
519+
bool early_deadlock = false;
519520
PROC *proc;
520521
int i;
521-
522522
#ifndef __BEOS__
523523
struct itimerval timeval,
524524
dummy;
525-
526525
#else
527526
bigtime_t time_interval;
528-
529527
#endif
530528

531529
/*
@@ -545,7 +543,6 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
545543
* immediately. This is the same as the test for immediate grant in
546544
* LockAcquire, except we are only considering the part of the wait
547545
* queue before my insertion point.
548-
*
549546
*/
550547
if (myHeldLocks != 0)
551548
{
@@ -560,9 +557,14 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
560557
/* Must I wait for him ? */
561558
if (lockctl->conflictTab[lockmode] & proc->heldLocks)
562559
{
563-
/* Yes, can report deadlock failure immediately */
564-
MyProc->errType = STATUS_ERROR;
565-
return STATUS_ERROR;
560+
/*
561+
* Yes, so we have a deadlock. Easiest way to clean up
562+
* correctly is to call RemoveFromWaitQueue(), but we
563+
* can't do that until we are *on* the wait queue.
564+
* So, set a flag to check below, and break out of loop.
565+
*/
566+
early_deadlock = true;
567+
break;
566568
}
567569
/* I must go before this waiter. Check special case. */
568570
if ((lockctl->conflictTab[lockmode] & aheadRequests) == 0 &&
@@ -610,7 +612,19 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
610612
MyProc->waitHolder = holder;
611613
MyProc->waitLockMode = lockmode;
612614

613-
MyProc->errType = STATUS_OK;/* initialize result for success */
615+
MyProc->errType = STATUS_OK; /* initialize result for success */
616+
617+
/*
618+
* If we detected deadlock, give up without waiting. This must agree
619+
* with HandleDeadLock's recovery code, except that we shouldn't release
620+
* the semaphore since we haven't tried to lock it yet.
621+
*/
622+
if (early_deadlock)
623+
{
624+
RemoveFromWaitQueue(MyProc);
625+
MyProc->errType = STATUS_ERROR;
626+
return STATUS_ERROR;
627+
}
614628

615629
/* mark that we are waiting for a lock */
616630
waitingForLock = true;
@@ -703,6 +717,10 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
703717
*
704718
* Also remove the process from the wait queue and set its links invalid.
705719
* RETURN: the next process in the wait queue.
720+
*
721+
* XXX: presently, this code is only used for the "success" case, and only
722+
* works correctly for that case. To clean up in failure case, would need
723+
* to twiddle the lock's request counts too --- see RemoveFromWaitQueue.
706724
*/
707725
PROC *
708726
ProcWakeup(PROC *proc, int errType)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy