From abc98dcc152bd3d8e2661c0f50988638725e838d Mon Sep 17 00:00:00 2001 From: Tom Lane 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 55fba035a9..f90a3fd0e8 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; } }