Thread
Commits
-
Fix tuple_data_split() to not open a relation without any lock.
- ec5f71aeadf9 9.6.11 landed
- b66827ca7c5a 12.0 landed
- 370b28ccd430 10.6 landed
- 1f25c7a8fc99 11.0 landed
-
Lock relation used to generate fresh data for RMV.
- de0bea8d4d81 9.3.25 landed
-
Fix ALTER COLUMN TYPE to not open a relation without any lock.
- db01fc97ad80 10.6 landed
- 26318c4b858a 9.4.20 landed
- 0360c539f2a2 9.6.11 landed
- 00d00b5b0d12 9.3.25 landed
- 0031e9d6ab80 9.5.15 landed
- e27453bd839f 12.0 landed
- 4c985549fe82 11.0 landed
-
Relations being opened without any lock whatever
Tom Lane <tgl@sss.pgh.pa.us> — 2018-09-30T19:20:44Z
Running the regression tests with the patch I showed in https://www.postgresql.org/message-id/16565.1538327894@sss.pgh.pa.us exposes two places where HEAD is opening relations without having any lock at all on them: 1. ALTER TABLE ... ALTER COLUMN TYPE, on a column that is part of a foreign key constraint, opens the rel that has the other end of the constraint before it's acquired a lock on said rel. The comment in ATPostAlterTypeCleanup claims this is "safe because the parser won't actually look at the catalogs to detect the existing entry", but I think that's largely horsepucky. The parser absolutely does do relation_open, and it expects the caller to have gotten a lock sufficient to protect that (cf transformAlterTableStmt). It's possible that this doesn't have any real effect. Since we're already holding AccessExclusiveLock on our own end of the FK constraint, it'd be impossible for another session to drop the FK constraint, or by extension the other table. Still, running a relcache load on a table we have no lock on seems pretty unsafe, especially so in branches before we used MVCC for catalog reads. So I'm inclined to apply the attached patch all the way back. (The mentioned comment also needs rewritten; this is just the minimal code change to get rid of the test failure.) 2. pageinspect's tuple_data_split_internal supposes that it needs no lock on the referenced table. Perhaps there was an expectation that some earlier function would have taken a lock and not released it, but this is demonstrably not happening in the module's own regression test. I think we should just take AccessShareLock there and not try to be cute. Again, this seems to be back-patch material. Thoughts, objections? regards, tom lane
-
Re: Relations being opened without any lock whatever
Michael Paquier <michael@paquier.xyz> — 2018-09-30T23:29:19Z
On Sun, Sep 30, 2018 at 03:20:44PM -0400, Tom Lane wrote: > 1. ALTER TABLE ... ALTER COLUMN TYPE, on a column that is part of > a foreign key constraint, opens the rel that has the other end of > the constraint before it's acquired a lock on said rel. > > The comment in ATPostAlterTypeCleanup claims this is "safe because the > parser won't actually look at the catalogs to detect the existing entry", > but I think that's largely horsepucky. The parser absolutely does do > relation_open, and it expects the caller to have gotten a lock sufficient > to protect that (cf transformAlterTableStmt). > > It's possible that this doesn't have any real effect. Since we're > already holding AccessExclusiveLock on our own end of the FK constraint, > it'd be impossible for another session to drop the FK constraint, or > by extension the other table. Still, running a relcache load on a > table we have no lock on seems pretty unsafe, especially so in branches > before we used MVCC for catalog reads. So I'm inclined to apply the > attached patch all the way back. (The mentioned comment also needs > rewritten; this is just the minimal code change to get rid of the test > failure.) Okay, that's bad. Wouldn't it be sufficient to use what the caller passes out as lockmode instead of enforcing AEL though? > 2. pageinspect's tuple_data_split_internal supposes that it needs no > lock on the referenced table. Perhaps there was an expectation that > some earlier function would have taken a lock and not released it, > but this is demonstrably not happening in the module's own regression > test. I think we should just take AccessShareLock there and not try > to be cute. Again, this seems to be back-patch material. Yes, that's incorrect. So +1 on this one. -- Michael
-
Re: Relations being opened without any lock whatever
Tom Lane <tgl@sss.pgh.pa.us> — 2018-10-01T00:08:28Z
Michael Paquier <michael@paquier.xyz> writes: > Okay, that's bad. Wouldn't it be sufficient to use what the caller > passes out as lockmode instead of enforcing AEL though? No, because at the bottom of that function we're going to do a DROP CONSTRAINT on the old FK constraint, and that needs AEL anyway. If we tried to take a lesser lock first we'd just be creating a lock-upgrade deadlock risk. regards, tom lane
-
Re: Relations being opened without any lock whatever
Amit Langote <langote_amit_f8@lab.ntt.co.jp> — 2018-10-01T07:19:58Z
On 2018/10/01 4:20, Tom Lane wrote: > Running the regression tests with the patch I showed in > https://www.postgresql.org/message-id/16565.1538327894@sss.pgh.pa.us > exposes two places where HEAD is opening relations without having > any lock at all on them: Maybe you've noticed but the relation_open calls coming from bootstrap.c all pass NoLock which trigger the WARNING: $ initdb -D /tmp/foo <snip> WARNING: relation_open: no lock held on pg_type WARNING: relation_open: no lock held on pg_attrdef WARNING: relation_open: no lock held on pg_constraint WARNING: relation_open: no lock held on pg_inherits WARNING: relation_open: no lock held on pg_index WARNING: relation_open: no lock held on pg_operator WARNING: relation_open: no lock held on pg_opfamily <so on> Do we need to do something about that, like teaching boot_openrel() and gettype() in bootstrap.c to pass AccessShareLock instead of NoLock? Thanks, Amit
-
Re: Relations being opened without any lock whatever
Tom Lane <tgl@sss.pgh.pa.us> — 2018-10-01T13:29:18Z
Amit Langote <Langote_Amit_f8@lab.ntt.co.jp> writes: > On 2018/10/01 4:20, Tom Lane wrote: >> Running the regression tests with the patch I showed in >> https://www.postgresql.org/message-id/16565.1538327894@sss.pgh.pa.us > Maybe you've noticed but the relation_open calls coming from bootstrap.c > all pass NoLock which trigger the WARNING: Yeah, I'd missed noticing that at the time I posted that patch, but I sure noticed after changing the WARNING to an Assert ;-) > Do we need to do something about that, like teaching boot_openrel() and > gettype() in bootstrap.c to pass AccessShareLock instead of NoLock? No, bootstrap mode has no need for locking. I think the right fix is just to skip the check: + /* + * If we didn't get the lock ourselves, assert that caller holds one, + * except in bootstrap mode where no locks are used. + */ + Assert(lockmode != NoLock || + IsBootstrapProcessingMode() || + CheckRelationLockedByMe(r, AccessShareLock, true)); It's possible that at some point we'd decide to make bootstrap mode do locking the same as normal mode, but that's not a change I want to make as part of this patch. regards, tom lane