When LockAcquire fails at the stage of creating a proclock object, be
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 12 Sep 2004 18:30:50 +0000 (18:30 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 12 Sep 2004 18:30:50 +0000 (18:30 +0000)
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

index 55fba035a91b9cbaeddf8e6c3eb3940b132cc84f..f90a3fd0e841198ca8a36640b4d954cb8033cb9c 100644 (file)
@@ -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;
            }
        }