aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2001-09-04 02:26:57 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2001-09-04 02:26:57 +0000
commitb553cba15a0ffb969e3025e6c65e01bb6971ddd6 (patch)
tree9863646fbc6e70b9ae970dc3ccb540e773bde103 /src
parent3c59a9e3b7050c6853e907ba28242059bb626790 (diff)
downloadpostgresql-b553cba15a0ffb969e3025e6c65e01bb6971ddd6.tar.gz
postgresql-b553cba15a0ffb969e3025e6c65e01bb6971ddd6.zip
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??
Diffstat (limited to 'src')
-rw-r--r--src/backend/storage/lmgr/proc.c36
1 files changed, 27 insertions, 9 deletions
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 9fc91d06cdb..f491bc16f70 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -8,7 +8,7 @@
*
*
* 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;
PROC_QUEUE *waitQueue = &(lock->waitProcs);
int myHeldLocks = MyProc->heldLocks;
+ bool early_deadlock = false;
PROC *proc;
int i;
-
#ifndef __BEOS__
struct itimerval timeval,
dummy;
-
#else
bigtime_t time_interval;
-
#endif
/*
@@ -535,7 +533,6 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
* immediately. This is the same as the test for immediate grant in
* LockAcquire, except we are only considering the part of the wait
* queue before my insertion point.
- *
*/
if (myHeldLocks != 0)
{
@@ -550,9 +547,14 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
/* Must I wait for him ? */
if (lockctl->conflictTab[lockmode] & proc->heldLocks)
{
- /* Yes, can report deadlock failure immediately */
- MyProc->errType = STATUS_ERROR;
- return STATUS_ERROR;
+ /*
+ * Yes, so we have a deadlock. Easiest way to clean up
+ * 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. */
if ((lockctl->conflictTab[lockmode] & aheadRequests) == 0 &&
@@ -600,7 +602,19 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
MyProc->waitHolder = holder;
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 */
waitingForLock = true;
@@ -693,6 +707,10 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
*
* Also remove the process from the wait queue and set its links invalid.
* 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 *
ProcWakeup(PROC *proc, int errType)