From abc98dcc152bd3d8e2661c0f50988638725e838d Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sun, 12 Sep 2004 18:30:50 +0000
Subject: [PATCH] When LockAcquire fails at the stage of creating a proclock
 object, be sure to clean up the already-created lock object, if it has no
 other references.  Avoids possibly-permanent leak of shared memory.

---
 src/backend/storage/lmgr/lock.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 55fba035a91..f90a3fd0e84 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.139 2004/08/29 05:06:48 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.140 2004/09/12 18:30:50 tgl Exp $
  *
  * NOTES
  *	  Outside modules can create a lock table and acquire/release
@@ -602,7 +602,23 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
 										HASH_ENTER, &found);
 	if (!proclock)
 	{
+		/* Ooops, not enough shmem for the proclock */
+		if (lock->nRequested == 0)
+		{
+			/*
+			 * There are no other requestors of this lock, so garbage-collect
+			 * the lock object.  We *must* do this to avoid a permanent leak
+			 * of shared memory, because there won't be anything to cause
+			 * anyone to release the lock object later.
+			 */
+			Assert(SHMQueueEmpty(&(lock->procLocks)));
+			lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid],
+										(void *) &(lock->tag),
+										HASH_REMOVE, NULL);
+		}
 		LWLockRelease(masterLock);
+		if (!lock)				/* hash remove failed? */
+			elog(WARNING, "lock table corrupted");
 		ereport(ERROR,
 				(errcode(ERRCODE_OUT_OF_MEMORY),
 				 errmsg("out of shared memory"),
@@ -1528,7 +1544,7 @@ LockReleaseAll(LOCKMETHODID lockmethodid, bool allxids)
 			if (!lock)
 			{
 				LWLockRelease(masterLock);
-				elog(WARNING, "cannot remove lock from HTAB");
+				elog(WARNING, "lock table corrupted");
 				return FALSE;
 			}
 		}
-- 
GitLab