diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 5848305a3518b4139211088d7223b4758aeb0946..4fe7d4012f042cf7192582c61ffee3be9bd429d9 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -319,6 +319,7 @@ DefineIndex(IndexStmt *stmt,
 	int16	   *coloptions;
 	IndexInfo  *indexInfo;
 	int			numberOfAttributes;
+	TransactionId limitXmin;
 	VirtualTransactionId *old_lockholders;
 	VirtualTransactionId *old_snapshots;
 	int			n_old_snapshots;
@@ -769,6 +770,18 @@ DefineIndex(IndexStmt *stmt,
 	 */
 	validate_index(relationId, indexRelationId, snapshot);
 
+	/*
+	 * Drop the reference snapshot.  We must do this before waiting out other
+	 * snapshot holders, else we will deadlock against other processes also
+	 * doing CREATE INDEX CONCURRENTLY, which would see our snapshot as one
+	 * they must wait for.  But first, save the snapshot's xmin to use as
+	 * limitXmin for GetCurrentVirtualXIDs().
+	 */
+	limitXmin = snapshot->xmin;
+
+	PopActiveSnapshot();
+	UnregisterSnapshot(snapshot);
+
 	/*
 	 * The index is now valid in the sense that it contains all currently
 	 * interesting tuples.	But since it might not contain tuples deleted just
@@ -801,7 +814,7 @@ DefineIndex(IndexStmt *stmt,
 	 * GetCurrentVirtualXIDs.  If, during any iteration, a particular vxid
 	 * doesn't show up in the output, we know we can forget about it.
 	 */
-	old_snapshots = GetCurrentVirtualXIDs(snapshot->xmin, true, false,
+	old_snapshots = GetCurrentVirtualXIDs(limitXmin, true, false,
 										  PROC_IS_AUTOVACUUM | PROC_IN_VACUUM,
 										  &n_old_snapshots);
 
@@ -818,7 +831,7 @@ DefineIndex(IndexStmt *stmt,
 			int			j;
 			int			k;
 
-			newer_snapshots = GetCurrentVirtualXIDs(snapshot->xmin,
+			newer_snapshots = GetCurrentVirtualXIDs(limitXmin,
 													true, false,
 										 PROC_IS_AUTOVACUUM | PROC_IN_VACUUM,
 													&n_newer_snapshots);
@@ -857,12 +870,6 @@ DefineIndex(IndexStmt *stmt,
 	 */
 	CacheInvalidateRelcacheByRelid(heaprelid.relId);
 
-	/* we can now do away with our active snapshot */
-	PopActiveSnapshot();
-
-	/* And we can remove the validating snapshot too */
-	UnregisterSnapshot(snapshot);
-
 	/*
 	 * Last thing to do is release the session-level lock on the parent table.
 	 */