0001-DROP-TABLE-race-in-expand_vacuum_rel-skip-lock-path.patch.nocfbot
application/octet-stream
Filename: 0001-DROP-TABLE-race-in-expand_vacuum_rel-skip-lock-path.patch.nocfbot
Type: application/octet-stream
Part: 0
From 3c3870959772869ceedc4445c5f88ff54f01b8ab Mon Sep 17 00:00:00 2001
From: Zsolt Parragi <parragizs@gmail.com>
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