diff options
author | Robert Haas <rhaas@postgresql.org> | 2012-04-18 11:17:30 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2012-04-18 11:17:30 -0400 |
commit | 53c5b869b464d567c3b8f617201b49a395f437ab (patch) | |
tree | 60377296105651401329bc604e06deb54a4e8216 /src/backend/storage/lmgr/proc.c | |
parent | ab77b2da8bf2cd1c8068f2f90e95c42d426aba3c (diff) | |
download | postgresql-53c5b869b464d567c3b8f617201b49a395f437ab.tar.gz postgresql-53c5b869b464d567c3b8f617201b49a395f437ab.zip |
Tighten up error recovery for fast-path locking.
The previous code could cause a backend crash after BEGIN; SAVEPOINT a;
LOCK TABLE foo (interrupted by ^C or statement timeout); ROLLBACK TO
SAVEPOINT a; LOCK TABLE foo, and might have leaked strong-lock counts
in other situations.
Report by Zoltán Böszörményi; patch review by Jeff Davis.
Diffstat (limited to 'src/backend/storage/lmgr/proc.c')
-rw-r--r-- | src/backend/storage/lmgr/proc.c | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 2926c159bdc..d1bf264b131 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -635,17 +635,20 @@ IsWaitingForLock(void) } /* - * Cancel any pending wait for lock, when aborting a transaction. + * Cancel any pending wait for lock, when aborting a transaction, and revert + * any strong lock count acquisition for a lock being acquired. * * (Normally, this would only happen if we accept a cancel/die - * interrupt while waiting; but an ereport(ERROR) while waiting is - * within the realm of possibility, too.) + * interrupt while waiting; but an ereport(ERROR) before or during the lock + * wait is within the realm of possibility, too.) */ void -LockWaitCancel(void) +LockErrorCleanup(void) { LWLockId partitionLock; + AbortStrongLockAcquire(); + /* Nothing to do if we weren't waiting for a lock */ if (lockAwaited == NULL) return; @@ -709,7 +712,7 @@ ProcReleaseLocks(bool isCommit) if (!MyProc) return; /* If waiting, get off wait queue (should only be needed after error) */ - LockWaitCancel(); + LockErrorCleanup(); /* Release locks */ LockReleaseAll(DEFAULT_LOCKMETHOD, !isCommit); @@ -1019,7 +1022,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) * NOTE: this may also cause us to exit critical-section state, possibly * allowing a cancel/die interrupt to be accepted. This is OK because we * have recorded the fact that we are waiting for a lock, and so - * LockWaitCancel will clean up if cancel/die happens. + * LockErrorCleanup will clean up if cancel/die happens. */ LWLockRelease(partitionLock); @@ -1062,7 +1065,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) * don't, because we have no shared-state-change work to do after being * granted the lock (the grantor did it all). We do have to worry about * updating the locallock table, but if we lose control to an error, - * LockWaitCancel will fix that up. + * LockErrorCleanup will fix that up. */ do { @@ -1207,7 +1210,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) LWLockAcquire(partitionLock, LW_EXCLUSIVE); /* - * We no longer want LockWaitCancel to do anything. + * We no longer want LockErrorCleanup to do anything. */ lockAwaited = NULL; |