|
| 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