Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)