summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/utils/init/postinit.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 2ea04e4c771..86ecce6bdce 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -742,10 +742,6 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
strcpy(out_dbname, dbname);
}
- /* Now we can mark our PGPROC entry with the database ID */
- /* (We assume this is an atomic store so no lock is needed) */
- MyProc->databaseId = MyDatabaseId;
-
/*
* Now, take a writer's lock on the database we are trying to connect to.
* If there is a concurrently running DROP DATABASE on that database, this
@@ -753,9 +749,13 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
* pg_database).
*
* Note that the lock is not held long, only until the end of this startup
- * transaction. This is OK since we are already advertising our use of
- * the database in the PGPROC array; anyone trying a DROP DATABASE after
- * this point will see us there.
+ * transaction. This is OK since we will advertise our use of the
+ * database in the ProcArray before dropping the lock (in fact, that's the
+ * next thing to do). Anyone trying a DROP DATABASE after this point will
+ * see us in the array once they have the lock. Ordering is important for
+ * this because we don't want to advertise ourselves as being in this
+ * database until we have the lock; otherwise we create what amounts to a
+ * deadlock with CountOtherDBBackends().
*
* Note: use of RowExclusiveLock here is reasonable because we envision
* our session as being a concurrent writer of the database. If we had a
@@ -768,6 +768,20 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
RowExclusiveLock);
/*
+ * Now we can mark our PGPROC entry with the database ID.
+ *
+ * We assume this is an atomic store so no lock is needed; though actually
+ * things would work fine even if it weren't atomic. Anyone searching the
+ * ProcArray for this database's ID should hold the database lock, so they
+ * would not be executing concurrently with this store. A process looking
+ * for another database's ID could in theory see a chance match if it read
+ * a partially-updated databaseId value; but as long as all such searches
+ * wait and retry, as in CountOtherDBBackends(), they will certainly see
+ * the correct value on their next try.
+ */
+ MyProc->databaseId = MyDatabaseId;
+
+ /*
* Recheck pg_database to make sure the target database hasn't gone away.
* If there was a concurrent DROP DATABASE, this ensures we will die
* cleanly without creating a mess.