Make DROP INDEX lock the parent table before locking the index. This behavior
authorTom Lane
Sun, 15 Jun 2008 16:29:05 +0000 (16:29 +0000)
committerTom Lane
Sun, 15 Jun 2008 16:29:05 +0000 (16:29 +0000)
is necessary to avoid deadlock against ordinary queries, but we'd broken it
with recent changes that made the DROP machinery lock the index before
arriving at index_drop.  Per intermittent buildfarm failures.

src/backend/commands/tablecmds.c

index b3d21875b25df8ba601ed9119ceed8f2b0c03dd7..639cd7296e2af83287eb1031629702594b8516f1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.257 2008/06/15 01:25:53 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.258 2008/06/15 16:29:05 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -676,6 +676,28 @@ RemoveRelations(DropStmt *drop)
            continue;
        }
 
+       /*
+        * In DROP INDEX, attempt to acquire lock on the parent table before
+        * locking the index.  index_drop() will need this anyway, and since
+        * regular queries lock tables before their indexes, we risk deadlock
+        * if we do it the other way around.  No error if we don't find a
+        * pg_index entry, though --- that most likely means it isn't an
+        * index, and we'll fail below.
+        */
+       if (relkind == RELKIND_INDEX)
+       {
+           tuple = SearchSysCache(INDEXRELID,
+                                  ObjectIdGetDatum(relOid),
+                                  0, 0, 0);
+           if (HeapTupleIsValid(tuple))
+           {
+               Form_pg_index index = (Form_pg_index) GETSTRUCT(tuple);
+
+               LockRelationOid(index->indrelid, AccessExclusiveLock);
+               ReleaseSysCache(tuple);
+           }
+       }
+
        /* Get the lock before trying to fetch the syscache entry */
        LockRelationOid(relOid, AccessExclusiveLock);