Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wRyEu-002qhA-3B for pgsql-hackers@arkaria.postgresql.org; Tue, 26 May 2026 20:19:01 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wRyEr-005r6J-1H for pgsql-hackers@arkaria.postgresql.org; Tue, 26 May 2026 20:18:58 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wRyEr-005r6A-0E for pgsql-hackers@lists.postgresql.org; Tue, 26 May 2026 20:18:58 +0000 Received: from mail-wm1-x333.google.com ([2a00:1450:4864:20::333]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wRyEp-00000001Zod-2Hgt for pgsql-hackers@lists.postgresql.org; Tue, 26 May 2026 20:18:57 +0000 Received: by mail-wm1-x333.google.com with SMTP id 5b1f17b1804b1-49050ff7cbdso33910875e9.2 for ; Tue, 26 May 2026 13:18:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779826732; x=1780431532; darn=lists.postgresql.org; h=in-reply-to:content-transfer-encoding:content-disposition :mime-version:references:message-id:subject:cc:to:from:date:from:to :cc:subject:date:message-id:reply-to; bh=rFkXYyGLUggDOEN0BNUe8UEqKeqywoFFI0eLMMcKdUA=; b=EqpbeMV4L+7BVL0DYyc1lAUjPWIzNXeRiH/LR7HUk5AN+6F42+LD5cVqpxTdRL4Xd3 SPlU0pc1mODTu5LHWIh9sHvIXmL9+57cgKAuaPLLdFZQVUiiZU70fu74Q9nY6r+cZK2L 8GZRDev6f5Cn9+w0lkKVxIqvZDNNxfQNpn+0RG2vsEcZjmgP/A4ts5y8OAYv3xQeI9BA i+YVux+0w7tmqksF5JfZs8XOhIyaEcqwU2+J4mkkSJ1KRhUMzE8SJ4iGABiMs6FJeZ4q 9EhUF+e76kN9x/Ga8i1r5WTuinzkM8qPaz5027g7rj44ewlWpMnzVfsJE9z0x05ZJEDf 2peA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779826732; x=1780431532; h=in-reply-to:content-transfer-encoding:content-disposition :mime-version:references:message-id:subject:cc:to:from:date:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=rFkXYyGLUggDOEN0BNUe8UEqKeqywoFFI0eLMMcKdUA=; b=EMbb6u4ZXp2RCuHmFBYF+GjoxI+76P/d8s67i4Le966xXlpdyqKGHVESpo8joozK+Y bZ/jAusVROdu+m6yt3ROiSlwmmc/WAylO8bc9kfQOMljToOmcC2/hbHFBBI1QWrE6M5h NehXAufCm2DjbK01IUkL5yiyXLtnmAf+RSJ/f3HsE+GQMxDBAOOe+XZnbB7hSxyYlMJs BTDGgAuIL5GSMe3r2U+SjRdBJrQCIsSdo0R8qGVGvA56TTmxeZtuJkv8MwgITsQOccsI qOxthGDN1Myakl6gkZxlwRFuBHZx03Mme4BNO2j/Ka6pn7yf0tuQG1qah+6uy1LnTO64 04AQ== X-Forwarded-Encrypted: i=1; AFNElJ8iFC3a/CW1Xle8REbaCjaczD+TFRT/XAydo3LorOPd2YH06DdBoVCI5xqEVQR9AA7rc5PcXnBfgB3Gp/+v@lists.postgresql.org X-Gm-Message-State: AOJu0YzetBOAErB+w8wUvZrYNsz+dsA1WPtGHRuNt5byzPCvm47vUA3+ h3KMGIGk6yIOvxW00UZf1v4Kii4hZ+t1Jv7pQn9VQLjHnvGMk9aQwLAO X-Gm-Gg: Acq92OH+t3o5X2lsjB4FhlXG0CDl8DTcmUdmWgFr76FUGIDQDYFqYAPs60W0GYxrecN Gh2IsD1EQQ0IFbllUEUR3x7NLxPxxgjqnTLDXMe3L2feBh2W9jWDRXi25im2fmbtzD8qWNeuG7m FPGQr0g2buKlHy/7WZy3nMzHuhc5Ch/EaXVCuvmp0RDJHululBp/ZkbLtIUTitH+F+fT+zU7HeB wXQcbj3wt4bYrJ2eTLQRdNir+KAsy2jWRBtD3zGhgfm9Cj5LHy4mZd24eCo6OHSqkyiCHzyXnve WcdzHuH6p+uXwSpQwO51wBp2Hl1Y+c5ZBSh9F/DkcTxILlod0Plvf4NKb6aP67fqT5KuZ+JlrJT QwLaRTf5J/DjJA4+50+X1KSkhVhhMZS+PuUEv/uDRPxSu+r3JpzKwOz6i9bg9f98wHaa/bpz2Wj k5wDsqSMSugFE/UF0vyzltJge4BKrSTHEnInSgDG1s6agNjr399E8fRjbCMzXSbDMrdsKtKs/rl HXPiNt6Eg0q+hHLOY92ow== X-Received: by 2002:a05:600c:3b12:b0:490:545c:7a8a with SMTP id 5b1f17b1804b1-490545c7c2emr238892915e9.20.1779826731879; Tue, 26 May 2026 13:18:51 -0700 (PDT) Received: from bdtpg (ec2-15-237-197-144.eu-west-3.compute.amazonaws.com. [15.237.197.144]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-45edb5a28casm821336f8f.23.2026.05.26.13.18.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 May 2026 13:18:51 -0700 (PDT) Date: Tue, 26 May 2026 20:18:50 +0000 From: Bertrand Drouvot To: Heikki Linnakangas Cc: Robert Haas , Jeff Davis , Roman Eskin , Michael Paquier , Alexander Lakhin , pgsql-hackers@lists.postgresql.org, Tom Lane Subject: Re: Avoid orphaned objects dependencies, take 3 Message-ID: References: <9f5f0dd4-96d5-4d90-9436-62d96e0298f9@arenadata.io> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Hi, On Tue, May 26, 2026 at 09:00:11PM +0300, Heikki Linnakangas wrote: > On 18/05/2026 15:14, Bertrand Drouvot wrote: > > On Wed, May 13, 2026 at 04:20:21PM -0400, Robert Haas wrote: > > > On Tue, Apr 28, 2026 at 7:17 AM Bertrand Drouvot > > > wrote: > > > > 0003: Add Assert guard to detect permission check before lock regressions > > > > > > > > Add instrumentation under USE_ASSERT_CHECKING to detect cases where object_aclcheck() > > > > is called on a referenced object before a lock is held on it, which would widen > > > > the TOCTOU window between the permission check and the dependency recording. > > > > > > I really like the idea of having some kind of cross-check system that > > > can detect future (or current) coding mistakes. > > > > Thanks for the feedback! BTW, it detected a new one due to 4793fc41f82, so v21 > > attached does fix it to make the CI green. > > I had a closer look at patch 0001. Thanks! > It doesn't fix all the problems, we > definitely need patch 0002/0003 too, but it's a good step forward and I > think it makes sense to commit it independently. Yeah, this will prevent orphaned objects which is a good step forward. > So I'm focusing on that > now. Thanks! I'll resume working on something similar to 0002 and 0003 once 0001 gets in. > I noticed we are already doing essentially the same thing for shared > dependencies, in shdepLockAndCheckObject(). I see that you even copied the > function comment from shdepLockAndCheckObject() to LockNotPinnedObject(), > but I didn't see it being otherwise mentioned in this thread. In any case, > that's a good argument for doing the same for non-shared dependencies that > we already do for shared dependencies. Right. > > + if (object->classId == RelationRelationId) > > + { > > + /* skip shared relations as they are pinned */ > > + if (IsSharedRelation(object->objectId)) > > + return; > > + > > + /* > > + * We must be in one of the two following cases that would already > > + * prevent the relation to be dropped: 1. The relation is already > > + * locked (could be an existing relation or a relation that we are > > + * creating). 2. The relation is protected indirectly (i.e an index > > + * protected by a lock on its table, a table protected by a lock on a > > + * function that depends of the table...). To avoid any risks, acquire > > + * a lock if there is none. That may add unnecessary lock for 2. but > > + * that's worth it. > > + */ > > + if (!CheckRelationOidLockedByMe(object->objectId, AccessShareLock, true)) > > + LockRelationOid(object->objectId, AccessShareLock); > > + return; > > + } > > Hmm, shouldn't that re-check that the relation exists, after acquiring the > lock, like the non-relation codepath does? Otherwise it's a little pointless > to acquire the lock. Good catch! Your change: + if (CheckRelationOidLockedByMe(objectId, AccessShareLock, true)) + return; + LockRelationOid(objectId, AccessShareLock); + + if (SearchSysCacheExists1(RELOID, ObjectIdGetDatum(objectId))) + return; + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("dependent relation was concurrently dropped"))); Looks good to me. > I did a bunch of little refactorings and ended up with the attached. Notable > changes: > > - I renamed and moved LockNotPinnedObject() into > dependencyLockAndCheckObject(), for consistency with > shdepLockAndCheckObject(). Makes sense to me. > - Removed ObjectByIdExist(), inlined it into the caller. The argument to use > SnapshotSelf or not seemed a bit too special to be generally useful Yeah, better to have this logic inlined as it will probably not be useful outside of it. > - Changed the error message and code to rhyme with the existing "role > was concurrently dropped" errors. I didn't add the OID to the error message > however, because that makes the testing hard. Agreed that's better. > - Added a test for a dependency on a role too, to cover the existing > shdepLockAndCheckObject() function. It's currently disabled because it > prints the OID, though. Nit: It also adds: +# function - role +permutation "s1_begin" "s1_alter_function_owner" "s2_drop_role" "s1_commit" That is not disabled and would already pass without the changes added in 0001. So I wonder if we could just start by adding this new test (and the XXX one) in a dedicated patch and then add 0001 that would focus on orphaned stuff only. A few comments: 1/ +#include "catalog/index.h" That doesn't look needed. 2/ It looks like pgindent "complains" on pg_depend.c for dependencyLockAndCheckObject(). Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com