Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit d2b7488

Browse files
committed
Add tap test for pg_signal_autovacuum role
This commit provides testig coverage for ccd3802, checking that a role granted pg_signal_autovacuum_worker is able to stop a vacuum worker. An injection point with a wait is placed at the beginning of autovacuum worker startup to make sure that a worker is still alive when sending and processing the signal sent. Author: Anthony Leung, Michael Paquier, Kirill Reshke Reviewed-by: Andrey Borodin, Nathan Bossart Discussion: https://postgr.es/m/CALdSSPiQPuuQpOkF7x0g2QkA5eE-3xXt7hiJFvShV1bHKDvf8w@mail.gmail.com
1 parent 47ecbfd commit d2b7488

File tree

3 files changed

+104
-1
lines changed

3 files changed

+104
-1
lines changed

src/backend/postmaster/autovacuum.c

+7
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
#include "utils/fmgroids.h"
101101
#include "utils/fmgrprotos.h"
102102
#include "utils/guc_hooks.h"
103+
#include "utils/injection_point.h"
103104
#include "utils/lsyscache.h"
104105
#include "utils/memutils.h"
105106
#include "utils/ps_status.h"
@@ -1902,6 +1903,12 @@ do_autovacuum(void)
19021903
/* Start a transaction so our commands have one to play into. */
19031904
StartTransactionCommand();
19041905

1906+
/*
1907+
* This injection point is put in a transaction block to work with a wait
1908+
* that uses a condition variable.
1909+
*/
1910+
INJECTION_POINT("autovacuum-worker-start");
1911+
19051912
/*
19061913
* Compute the multixact age for which freezing is urgent. This is
19071914
* normally autovacuum_multixact_freeze_max_age, but may be less if we are

src/test/modules/test_misc/meson.build

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ tests += {
1313
't/002_tablespace.pl',
1414
't/003_check_guc.pl',
1515
't/004_io_direct.pl',
16-
't/005_timeouts.pl'
16+
't/005_timeouts.pl',
17+
't/006_signal_autovacuum.pl',
1718
],
1819
},
1920
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Copyright (c) 2024, PostgreSQL Global Development Group
2+
3+
# Test signaling autovacuum worker with pg_signal_autovacuum_worker.
4+
#
5+
# Only roles with privileges of pg_signal_autovacuum_worker are allowed to
6+
# signal autovacuum workers. This test uses an injection point located
7+
# at the beginning of the autovacuum worker startup.
8+
9+
use strict;
10+
use warnings;
11+
use PostgreSQL::Test::Cluster;
12+
use Test::More;
13+
14+
if ($ENV{enable_injection_points} ne 'yes')
15+
{
16+
plan skip_all => 'Injection points not supported by this build';
17+
}
18+
19+
# Initialize postgres
20+
my $psql_err = '';
21+
my $psql_out = '';
22+
my $node = PostgreSQL::Test::Cluster->new('node');
23+
$node->init;
24+
25+
# This ensures a quick worker spawn.
26+
$node->append_conf('postgresql.conf', 'autovacuum_naptime = 1');
27+
$node->start;
28+
$node->safe_psql('postgres', 'CREATE EXTENSION injection_points;');
29+
30+
$node->safe_psql(
31+
'postgres', qq(
32+
CREATE ROLE regress_regular_role;
33+
CREATE ROLE regress_worker_role;
34+
GRANT pg_signal_autovacuum_worker TO regress_worker_role;
35+
));
36+
37+
# From this point, autovacuum worker will wait at startup.
38+
$node->safe_psql('postgres',
39+
"SELECT injection_points_attach('autovacuum-worker-start', 'wait');");
40+
41+
# Accelerate worker creation in case we reach this point before the naptime
42+
# ends.
43+
$node->reload();
44+
45+
# Wait until an autovacuum worker starts.
46+
$node->wait_for_event('autovacuum worker', 'autovacuum-worker-start');
47+
48+
# And grab one of them.
49+
my $av_pid = $node->safe_psql(
50+
'postgres', qq(
51+
SELECT pid FROM pg_stat_activity WHERE backend_type = 'autovacuum worker' AND wait_event = 'autovacuum-worker-start' LIMIT 1;
52+
));
53+
54+
# Regular role cannot terminate autovacuum worker.
55+
my $terminate_with_no_pg_signal_av = $node->psql(
56+
'postgres', qq(
57+
SET ROLE regress_regular_role;
58+
SELECT pg_terminate_backend('$av_pid');
59+
),
60+
stdout => \$psql_out,
61+
stderr => \$psql_err);
62+
63+
like(
64+
$psql_err,
65+
qr/ERROR: permission denied to terminate process\nDETAIL: Only roles with privileges of the "pg_signal_autovacuum_worker" role may terminate autovacuum workers./,
66+
"autovacuum worker not signaled with regular role");
67+
68+
my $offset = -s $node->logfile;
69+
70+
# Role with pg_signal_autovacuum can terminate autovacuum worker.
71+
my $terminate_with_pg_signal_av = $node->psql(
72+
'postgres', qq(
73+
SET ROLE regress_worker_role;
74+
SELECT pg_terminate_backend('$av_pid');
75+
),
76+
stdout => \$psql_out,
77+
stderr => \$psql_err);
78+
79+
# Wait for the autovacuum worker to exit before scanning the logs.
80+
$node->poll_query_until('postgres',
81+
"SELECT count(*) = 0 FROM pg_stat_activity "
82+
. "WHERE pid = '$av_pid' AND backend_type = 'autovacuum worker';");
83+
84+
# Check that the primary server logs a FATAL indicating that autovacuum
85+
# is terminated.
86+
ok( $node->log_contains(
87+
qr/FATAL: terminating autovacuum process due to administrator command/,
88+
$offset),
89+
"autovacuum worker signaled with pg_signal_autovacuum_worker granted");
90+
91+
# Release injection point.
92+
$node->safe_psql('postgres',
93+
"SELECT injection_points_detach('autovacuum-worker-start');");
94+
95+
done_testing();

0 commit comments

Comments
 (0)