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,
506506SPINLOCK spinlock = lockctl -> masterLock ;
507507PROC_QUEUE * waitQueue = & (lock -> waitProcs );
508508int myHeldLocks = MyProc -> heldLocks ;
509+ bool early_deadlock = false;
509510PROC * proc ;
510511int i ;
511-
512512#ifndef __BEOS__
513513struct itimerval timeval ,
514514dummy ;
515-
516515#else
517516bigtime_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 */
540537if (myHeldLocks != 0 )
541538{
@@ -550,9 +547,14 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
550547/* Must I wait for him ? */
551548if (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. */
558560if ((lockctl -> conflictTab [lockmode ]& aheadRequests )== 0 &&
@@ -600,7 +602,19 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
600602MyProc -> waitHolder = holder ;
601603MyProc -> 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 */
606620waitingForLock = 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 */
697715PROC *
698716ProcWakeup (PROC * proc ,int errType )