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??
This commit is contained in:
parent
3c59a9e3b7
commit
b553cba15a
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.104 2001/07/06 21:04:26 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.105 2001/09/04 02:26:57 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -506,16 +506,14 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
|
|||||||
SPINLOCK spinlock = lockctl->masterLock;
|
SPINLOCK spinlock = lockctl->masterLock;
|
||||||
PROC_QUEUE *waitQueue = &(lock->waitProcs);
|
PROC_QUEUE *waitQueue = &(lock->waitProcs);
|
||||||
int myHeldLocks = MyProc->heldLocks;
|
int myHeldLocks = MyProc->heldLocks;
|
||||||
|
bool early_deadlock = false;
|
||||||
PROC *proc;
|
PROC *proc;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#ifndef __BEOS__
|
#ifndef __BEOS__
|
||||||
struct itimerval timeval,
|
struct itimerval timeval,
|
||||||
dummy;
|
dummy;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
bigtime_t time_interval;
|
bigtime_t time_interval;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -535,7 +533,6 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
|
|||||||
* immediately. This is the same as the test for immediate grant in
|
* immediately. This is the same as the test for immediate grant in
|
||||||
* LockAcquire, except we are only considering the part of the wait
|
* LockAcquire, except we are only considering the part of the wait
|
||||||
* queue before my insertion point.
|
* queue before my insertion point.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
if (myHeldLocks != 0)
|
if (myHeldLocks != 0)
|
||||||
{
|
{
|
||||||
@ -550,9 +547,14 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
|
|||||||
/* Must I wait for him ? */
|
/* Must I wait for him ? */
|
||||||
if (lockctl->conflictTab[lockmode] & proc->heldLocks)
|
if (lockctl->conflictTab[lockmode] & proc->heldLocks)
|
||||||
{
|
{
|
||||||
/* Yes, can report deadlock failure immediately */
|
/*
|
||||||
MyProc->errType = STATUS_ERROR;
|
* Yes, so we have a deadlock. Easiest way to clean up
|
||||||
return STATUS_ERROR;
|
* correctly is to call RemoveFromWaitQueue(), but we
|
||||||
|
* can't do that until we are *on* the wait queue.
|
||||||
|
* So, set a flag to check below, and break out of loop.
|
||||||
|
*/
|
||||||
|
early_deadlock = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
/* I must go before this waiter. Check special case. */
|
/* I must go before this waiter. Check special case. */
|
||||||
if ((lockctl->conflictTab[lockmode] & aheadRequests) == 0 &&
|
if ((lockctl->conflictTab[lockmode] & aheadRequests) == 0 &&
|
||||||
@ -600,7 +602,19 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
|
|||||||
MyProc->waitHolder = holder;
|
MyProc->waitHolder = holder;
|
||||||
MyProc->waitLockMode = lockmode;
|
MyProc->waitLockMode = lockmode;
|
||||||
|
|
||||||
MyProc->errType = STATUS_OK;/* initialize result for success */
|
MyProc->errType = STATUS_OK; /* initialize result for success */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we detected deadlock, give up without waiting. This must agree
|
||||||
|
* with HandleDeadLock's recovery code, except that we shouldn't release
|
||||||
|
* the semaphore since we haven't tried to lock it yet.
|
||||||
|
*/
|
||||||
|
if (early_deadlock)
|
||||||
|
{
|
||||||
|
RemoveFromWaitQueue(MyProc);
|
||||||
|
MyProc->errType = STATUS_ERROR;
|
||||||
|
return STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/* mark that we are waiting for a lock */
|
/* mark that we are waiting for a lock */
|
||||||
waitingForLock = true;
|
waitingForLock = true;
|
||||||
@ -693,6 +707,10 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
|
|||||||
*
|
*
|
||||||
* Also remove the process from the wait queue and set its links invalid.
|
* Also remove the process from the wait queue and set its links invalid.
|
||||||
* RETURN: the next process in the wait queue.
|
* RETURN: the next process in the wait queue.
|
||||||
|
*
|
||||||
|
* XXX: presently, this code is only used for the "success" case, and only
|
||||||
|
* works correctly for that case. To clean up in failure case, would need
|
||||||
|
* to twiddle the lock's request counts too --- see RemoveFromWaitQueue.
|
||||||
*/
|
*/
|
||||||
PROC *
|
PROC *
|
||||||
ProcWakeup(PROC *proc, int errType)
|
ProcWakeup(PROC *proc, int errType)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user