From 3c3870959772869ceedc4445c5f88ff54f01b8ab Mon Sep 17 00:00:00 2001 From: Zsolt Parragi Date: Thu, 14 May 2026 21:16:24 +0000 Subject: [PATCH] DROP TABLE race in expand_vacuum_rel skip-lock path --- src/backend/commands/vacuum.c | 1 + src/test/recovery/meson.build | 1 + .../t/053_vacuum_skip_locked_drop_race.pl | 54 +++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 src/test/recovery/t/053_vacuum_skip_locked_drop_race.pl diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 51c5fc2fdaf..0edb56e67c9 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -961,6 +961,7 @@ expand_vacuum_rel(VacuumRelation *vrel, MemoryContext vac_context, errmsg("skipping analyze of \"%s\" --- lock not available", vrel->relation->relname))); + INJECTION_POINT("expand-vacuum-rel-skip-locked", NULL); /* Get relid for statistics reporting */ relid = RangeVarGetRelid(vrel->relation, NoLock, true); diff --git a/src/test/recovery/meson.build b/src/test/recovery/meson.build index 36d789720a3..05190b26931 100644 --- a/src/test/recovery/meson.build +++ b/src/test/recovery/meson.build @@ -61,6 +61,7 @@ tests += { 't/050_redo_segment_missing.pl', 't/051_effective_wal_level.pl', 't/052_checkpoint_segment_missing.pl', + 't/053_vacuum_skip_locked_drop_race.pl', ], }, } diff --git a/src/test/recovery/t/053_vacuum_skip_locked_drop_race.pl b/src/test/recovery/t/053_vacuum_skip_locked_drop_race.pl new file mode 100644 index 00000000000..417f6ec2541 --- /dev/null +++ b/src/test/recovery/t/053_vacuum_skip_locked_drop_race.pl @@ -0,0 +1,54 @@ +use strict; +use warnings FATAL => 'all'; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +my $node = PostgreSQL::Test::Cluster->new('main'); +$node->init; +$node->start; + +$node->safe_psql( + 'postgres', q{ + CREATE EXTENSION injection_points; + CREATE TABLE foo (id int); + SELECT injection_points_attach('expand-vacuum-rel-skip-locked', 'wait'); +}); + +my $locker = $node->background_psql('postgres'); +$locker->query_safe(q{BEGIN; LOCK TABLE foo IN ACCESS EXCLUSIVE MODE;}); + +my $log_offset = -s $node->logfile; + +my $vacuumer = $node->background_psql('postgres'); +$vacuumer->query_until(qr/start/, + qq(\\echo start\nVACUUM (SKIP_LOCKED) foo;\n)); + +$node->wait_for_event('client backend', 'expand-vacuum-rel-skip-locked'); + +ok( $node->log_contains( + qr/skipping vacuum of "foo" --- lock not available/, + $log_offset), + 'VACUUM (SKIP_LOCKED) was skipped due to lock unavailability'); + +$locker->query_safe(q{ + COMMIT; + DROP TABLE foo; +}); +$locker->quit; + +$node->safe_psql('postgres', + q{SELECT injection_points_wakeup('expand-vacuum-rel-skip-locked');}); +$vacuumer->quit; + +$node->safe_psql('postgres', q{SELECT pg_stat_force_next_flush();}); + +my $total = $node->safe_psql('postgres', q{ + SELECT coalesce(sum(skipped_vacuum_count), 0) + FROM pg_stat_all_tables; +}); +chomp $total; + +cmp_ok($total, '>=', 1, 'skip event recorded in pg_stat_all_tables'); + +done_testing(); -- 2.54.0