aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/lmgr/proc.c
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2012-04-18 11:17:30 -0400
committerRobert Haas <rhaas@postgresql.org>2012-04-18 11:17:30 -0400
commit53c5b869b464d567c3b8f617201b49a395f437ab (patch)
tree60377296105651401329bc604e06deb54a4e8216 /src/backend/storage/lmgr/proc.c
parentab77b2da8bf2cd1c8068f2f90e95c42d426aba3c (diff)
downloadpostgresql-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.c19
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;