aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2021-07-11 12:54:24 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2021-07-11 12:54:24 -0400
commit1c612bc98ec363e2464cce66526b75a0d08d657e (patch)
tree9b8be770f6a5f6c1b5917c53938cfab13b81dc33
parentedd9a2bf741be95aa771b9fcacb2ce7378fb9121 (diff)
downloadpostgresql-1c612bc98ec363e2464cce66526b75a0d08d657e.tar.gz
postgresql-1c612bc98ec363e2464cce66526b75a0d08d657e.zip
Lock the extension during ALTER EXTENSION ADD/DROP.
Although we were careful to lock the object being added or dropped, we failed to get any sort of lock on the extension itself. This allowed the ALTER to proceed in parallel with a DROP EXTENSION, which is problematic for a couple of reasons. If both commands succeeded we'd be left with a dangling link in pg_depend, which would cause problems later. Also, if the ALTER failed for some reason, it might try to print the extension's name, and that could result in a crash or (in older branches) a silly error message complaining about extension "(null)". Per bug #17098 from Alexander Lakhin. Back-patch to all supported branches. Discussion: https://postgr.es/m/17098-b960f3616c861f83@postgresql.org
-rw-r--r--src/backend/commands/extension.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index b08f2b481c8..ed0691592ef 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -3282,9 +3282,17 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt,
Relation relation;
Oid oldExtension;
- extension.classId = ExtensionRelationId;
- extension.objectId = get_extension_oid(stmt->extname, false);
- extension.objectSubId = 0;
+ /*
+ * Find the extension and acquire a lock on it, to ensure it doesn't get
+ * dropped concurrently. A sharable lock seems sufficient: there's no
+ * reason not to allow other sorts of manipulations, such as add/drop of
+ * other objects, to occur concurrently. Concurrently adding/dropping the
+ * *same* object would be bad, but we prevent that by using a non-sharable
+ * lock on the individual object, below.
+ */
+ extension = get_object_address(OBJECT_EXTENSION,
+ (Node *) makeString(stmt->extname),
+ &relation, AccessShareLock, false);
/* Permission check: must own extension */
if (!pg_extension_ownercheck(extension.objectId, GetUserId()))