Re: Error in backend/storage/lmgr/proc.c: ProcSleep()

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Tomasz Zielonka <tomek(at)mult(dot)i(dot)pl>
Cc: PostgreSQL bugs <pgsql-bugs(at)postgresql(dot)org>
Subject: Re: Error in backend/storage/lmgr/proc.c: ProcSleep()
Date: 2001-09-04 02:37:11
Message-ID: 24206.999571031@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

Tomasz Zielonka <tomek(at)mult(dot)i(dot)pl> writes:
> Platform: PostgreSQL 7.1.3, Linux 2.4.8, egcs 2.91.66
> PostgreSQL forgets to release lock until shutdown in this scenario:

Good catch! This has been broken since 7.1 ... surprising that no one
discovered the problem sooner.

I think that rather than removing the early-deadlock-detection code as
you suggest, it's better to make it work correctly. I have applied a
patch that allows RemoveFromWaitQueue() to be used, so that the recovery
path is the same as if HandleDeadLock had been invoked.

regards, tom lane

*** /home/postgres/pgsql/src/backend/storage/lmgr/proc.c.orig Fri Jul 6 17:04:26 2001
--- /home/postgres/pgsql/src/backend/storage/lmgr/proc.c Mon Sep 3 22:26:57 2001
***************
*** 506,521 ****
SPINLOCK spinlock = lockctl->masterLock;
PROC_QUEUE *waitQueue = &(lock->waitProcs);
int myHeldLocks = MyProc->heldLocks;
PROC *proc;
int i;
-
#ifndef __BEOS__
struct itimerval timeval,
dummy;
-
#else
bigtime_t time_interval;
-
#endif

/*
--- 506,519 ----
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,541 ****
* 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)
{
--- 533,538 ----
***************
*** 550,558 ****
/* Must I wait for him ? */
if (lockctl->conflictTab[lockmode] & proc->heldLocks)
{
! /* Yes, can report deadlock failure immediately */
! MyProc->errType = STATUS_ERROR;
! return STATUS_ERROR;
}
/* I must go before this waiter. Check special case. */
if ((lockctl->conflictTab[lockmode] & aheadRequests) == 0 &&
--- 547,560 ----
/* Must I wait for him ? */
if (lockctl->conflictTab[lockmode] & proc->heldLocks)
{
! /*
! * 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,606 ****
MyProc->waitHolder = holder;
MyProc->waitLockMode = lockmode;

! MyProc->errType = STATUS_OK;/* initialize result for success */

/* mark that we are waiting for a lock */
waitingForLock = true;
--- 602,620 ----
MyProc->waitHolder = holder;
MyProc->waitLockMode = lockmode;

! 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;

In response to

Browse pgsql-bugs by date

  From Date Subject
Next Message pgsql-bugs 2001-09-04 03:33:19 Bug #437: postgresql-python rpm fails on mx dependency
Previous Message John Summerfield 2001-09-04 00:34:16 Logging problems in PostgreSQL 7.2devel