]> granicus.if.org Git - postgresql/commitdiff
Fix oversight in coding of _bt_start_vacuum: we can't assume that the LWLock
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 30 Mar 2007 00:12:59 +0000 (00:12 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 30 Mar 2007 00:12:59 +0000 (00:12 +0000)
will be released by transaction abort before _bt_end_vacuum gets called.
If either of these "can't happen" errors actually happened, we'd freeze up
trying to acquire an already-held lock.  Latest word is that this does
not explain Martin Pitt's trouble report, but it still looks like a bug.

src/backend/access/nbtree/nbtutils.c

index d453a93cafa61c2fc4bb259f81ab1220f83fb0a9..9c227d7f6c656650503b77b0fd1767ea3144633c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.82 2007/01/09 02:14:10 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.83 2007/03/30 00:12:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1214,13 +1214,25 @@ _bt_start_vacuum(Relation rel)
                vac = &btvacinfo->vacuums[i];
                if (vac->relid.relId == rel->rd_lockInfo.lockRelId.relId &&
                        vac->relid.dbId == rel->rd_lockInfo.lockRelId.dbId)
+               {
+                       /*
+                        * Unlike most places in the backend, we have to explicitly
+                        * release our LWLock before throwing an error.  This is because
+                        * we expect _bt_end_vacuum() to be called before transaction
+                        * abort cleanup can run to release LWLocks.
+                        */
+                       LWLockRelease(BtreeVacuumLock);
                        elog(ERROR, "multiple active vacuums for index \"%s\"",
                                 RelationGetRelationName(rel));
+               }
        }
 
        /* OK, add an entry */
        if (btvacinfo->num_vacuums >= btvacinfo->max_vacuums)
+       {
+               LWLockRelease(BtreeVacuumLock);
                elog(ERROR, "out of btvacinfo slots");
+       }
        vac = &btvacinfo->vacuums[btvacinfo->num_vacuums];
        vac->relid = rel->rd_lockInfo.lockRelId;
        vac->cycleid = result;