summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoah Misch2024-05-16 21:11:00 +0000
committerNoah Misch2024-05-16 21:11:00 +0000
commit372700cf3067254317e7e8060662f8fac11500d5 (patch)
tree4cb1af4322e066c1f19e3c1a2cbd819e44480f0b
parenta3e6c6f929912f928fa405909d17bcbf0c1b03ee (diff)
Fix documentation about DROP DATABASE FORCE process termination rights.
Specifically, it terminates a background worker even if the caller couldn't terminate the background worker with pg_terminate_backend(). Commit 3a9b18b3095366cd0c4305441d426d04572d88c1 neglected to update this. Back-patch to v13, which introduced DROP DATABASE FORCE. Reviewed by Amit Kapila. Reported by Kirill Reshke. Discussion: https://postgr.es/m/[email protected]
-rw-r--r--doc/src/sgml/ref/drop_database.sgml12
-rw-r--r--src/backend/storage/ipc/procarray.c25
2 files changed, 21 insertions, 16 deletions
diff --git a/doc/src/sgml/ref/drop_database.sgml b/doc/src/sgml/ref/drop_database.sgml
index ff01450ba77..55c52ae93bc 100644
--- a/doc/src/sgml/ref/drop_database.sgml
+++ b/doc/src/sgml/ref/drop_database.sgml
@@ -79,12 +79,14 @@ DROP DATABASE [ IF EXISTS ] <replaceable class="parameter">name</replaceable> [
It doesn't terminate if prepared transactions, active logical replication
slots or subscriptions are present in the target database.
</para>
+ <!-- not mentioning exception for autovacuum workers, since those are an
+ implementation detail and the exception is not specific to FORCE -->
<para>
- This will fail if the current user has no permissions to terminate other
- connections. Required permissions are the same as with
- <literal>pg_terminate_backend</literal>, described in
- <xref linkend="functions-admin-signal"/>. This will also fail if we
- are not able to terminate connections.
+ This terminates background worker connections and connections that the
+ current user has permission to terminate
+ with <function>pg_terminate_backend</function>, described in
+ <xref linkend="functions-admin-signal"/>. If connections would remain,
+ this command will fail.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 1a83c4220b2..d5165aa0d9f 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -3808,8 +3808,8 @@ CountOtherDBBackends(Oid databaseId, int *nbackends, int *nprepared)
* The current backend is always ignored; it is caller's responsibility to
* check whether the current backend uses the given DB, if it's important.
*
- * It doesn't allow to terminate the connections even if there is a one
- * backend with the prepared transaction in the target database.
+ * If the target database has a prepared transaction or permissions checks
+ * fail for a connection, this fails without terminating anything.
*/
void
TerminateOtherDBBackends(Oid databaseId)
@@ -3854,14 +3854,19 @@ TerminateOtherDBBackends(Oid databaseId)
ListCell *lc;
/*
- * Check whether we have the necessary rights to terminate other
- * sessions. We don't terminate any session until we ensure that we
- * have rights on all the sessions to be terminated. These checks are
- * the same as we do in pg_terminate_backend.
+ * Permissions checks relax the pg_terminate_backend checks in two
+ * ways, both by omitting the !OidIsValid(proc->roleId) check:
*
- * In this case we don't raise some warnings - like "PID %d is not a
- * PostgreSQL server process", because for us already finished session
- * is not a problem.
+ * - Accept terminating autovacuum workers, since DROP DATABASE
+ * without FORCE terminates them.
+ *
+ * - Accept terminating bgworkers. For bgworker authors, it's
+ * convenient to be able to recommend FORCE if a worker is blocking
+ * DROP DATABASE unexpectedly.
+ *
+ * Unlike pg_terminate_backend, we don't raise some warnings - like
+ * "PID %d is not a PostgreSQL server process", because for us already
+ * finished session is not a problem.
*/
foreach(lc, pids)
{
@@ -3870,7 +3875,6 @@ TerminateOtherDBBackends(Oid databaseId)
if (proc != NULL)
{
- /* Only allow superusers to signal superuser-owned backends. */
if (superuser_arg(proc->roleId) && !superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
@@ -3878,7 +3882,6 @@ TerminateOtherDBBackends(Oid databaseId)
errdetail("Only roles with the %s attribute may terminate processes of roles with the %s attribute.",
"SUPERUSER", "SUPERUSER")));
- /* Users can signal backends they have role membership in. */
if (!has_privs_of_role(GetUserId(), proc->roleId) &&
!has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_BACKEND))
ereport(ERROR,