Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b553cba

Browse files
committed
Clean up the lock state properly when aborting because of early deadlock
detection in ProcSleep(). Bug noted by Tomasz Zielonka --- how did this escape detection for this long??
1 parent 3c59a9e commit b553cba

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.104 2001/07/06 21:04:26 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.105 2001/09/04 02:26:57 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -506,16 +506,14 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
506506
SPINLOCK spinlock = lockctl->masterLock;
507507
PROC_QUEUE *waitQueue = &(lock->waitProcs);
508508
int myHeldLocks = MyProc->heldLocks;
509+
bool early_deadlock = false;
509510
PROC *proc;
510511
int i;
511-
512512
#ifndef __BEOS__
513513
struct itimerval timeval,
514514
dummy;
515-
516515
#else
517516
bigtime_t time_interval;
518-
519517
#endif
520518

521519
/*
@@ -535,7 +533,6 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
535533
* immediately. This is the same as the test for immediate grant in
536534
* LockAcquire, except we are only considering the part of the wait
537535
* queue before my insertion point.
538-
*
539536
*/
540537
if (myHeldLocks != 0)
541538
{
@@ -550,9 +547,14 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
550547
/* Must I wait for him ? */
551548
if (lockctl->conflictTab[lockmode] & proc->heldLocks)
552549
{
553-
/* Yes, can report deadlock failure immediately */
554-
MyProc->errType = STATUS_ERROR;
555-
return STATUS_ERROR;
550+
/*
551+
* Yes, so we have a deadlock. Easiest way to clean up
552+
* correctly is to call RemoveFromWaitQueue(), but we
553+
* can't do that until we are *on* the wait queue.
554+
* So, set a flag to check below, and break out of loop.
555+
*/
556+
early_deadlock = true;
557+
break;
556558
}
557559
/* I must go before this waiter. Check special case. */
558560
if ((lockctl->conflictTab[lockmode] & aheadRequests) == 0 &&
@@ -600,7 +602,19 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
600602
MyProc->waitHolder = holder;
601603
MyProc->waitLockMode = lockmode;
602604

603-
MyProc->errType = STATUS_OK;/* initialize result for success */
605+
MyProc->errType = STATUS_OK; /* initialize result for success */
606+
607+
/*
608+
* If we detected deadlock, give up without waiting. This must agree
609+
* with HandleDeadLock's recovery code, except that we shouldn't release
610+
* the semaphore since we haven't tried to lock it yet.
611+
*/
612+
if (early_deadlock)
613+
{
614+
RemoveFromWaitQueue(MyProc);
615+
MyProc->errType = STATUS_ERROR;
616+
return STATUS_ERROR;
617+
}
604618

605619
/* mark that we are waiting for a lock */
606620
waitingForLock = true;
@@ -693,6 +707,10 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
693707
*
694708
* Also remove the process from the wait queue and set its links invalid.
695709
* RETURN: the next process in the wait queue.
710+
*
711+
* XXX: presently, this code is only used for the "success" case, and only
712+
* works correctly for that case. To clean up in failure case, would need
713+
* to twiddle the lock's request counts too --- see RemoveFromWaitQueue.
696714
*/
697715
PROC *
698716
ProcWakeup(PROC *proc, int errType)

0 commit comments

Comments
 (0)