8000 Back-patch deadlock recovery fix into 7.1 tree, in case someone needs… · danielcode/postgres@e419d86 · GitHub
[go: up one dir, main page]

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)
0