diff options
author | Michael Paquier | 2025-03-04 05:09:44 +0000 |
---|---|---|
committer | Michael Paquier | 2025-03-04 05:09:44 +0000 |
commit | c76db55c9085d0b7984ea337576e45a7d1268b97 (patch) | |
tree | 29393607928688ec1276d7989dd154453a3fbcf8 /src/test/authentication | |
parent | 40d3f8274499cb1dd349f60f2e5915f907acce6e (diff) |
Split pgstat_bestart() into three different routines
pgstat_bestart(), used post-authentication to set up a backend entry
in the PgBackendStatus array, so as its data becomes visible in
pg_stat_activity and related catalogs, has its logic divided into three
routines with this commit, called in order at different steps of the
backend initialization:
* pgstat_bestart_initial() sets up the backend entry with a minimal
amount of information, reporting it with a new BackendState called
STATE_STARTING while waiting for backend initialization and client
authentication to complete. The main benefit that this offers is
observability, so as it is possible to monitor the backend activity
during authentication. This step happens earlier than in the logic
prior to this commit. pgstat_beinit() happens earlier as well, before
authentication.
* pgstat_bestart_security() reports the SSL/GSS status of the
connection, once authentication completes. Auxiliary processes, for
example, do not need to call this step, hence it is optional. This
step is called after performing authentication, same as previously.
* pgstat_bestart_final() reports the user and database IDs, takes the
entry out of STATE_STARTING, and reports its application_name. This is
called as the last step of the three, once authentication completes.
An injection point is added, with a test checking that the "starting"
phase of a backend entry is visible in pg_stat_activity. Some follow-up
patches are planned to take advantage of this refactoring with more
information provided in backend entries during authentication (LDAP
hanging was a problem for the author, initially).
Author: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/CAOYmi+=60deN20WDyCoHCiecgivJxr=98s7s7-C8SkXwrCfHXg@mail.gmail.com
Diffstat (limited to 'src/test/authentication')
-rw-r--r-- | src/test/authentication/Makefile | 4 | ||||
-rw-r--r-- | src/test/authentication/meson.build | 4 | ||||
-rw-r--r-- | src/test/authentication/t/007_pre_auth.pl | 81 |
3 files changed, 89 insertions, 0 deletions
diff --git a/src/test/authentication/Makefile b/src/test/authentication/Makefile index c4022dc829b..8b5beced080 100644 --- a/src/test/authentication/Makefile +++ b/src/test/authentication/Makefile @@ -13,6 +13,10 @@ subdir = src/test/authentication top_builddir = ../../.. include $(top_builddir)/src/Makefile.global +EXTRA_INSTALL = src/test/modules/injection_points + +export enable_injection_points + check: $(prove_check) diff --git a/src/test/authentication/meson.build b/src/test/authentication/meson.build index f6e48411c11..800b3a5ff40 100644 --- a/src/test/authentication/meson.build +++ b/src/test/authentication/meson.build @@ -5,6 +5,9 @@ tests += { 'sd': meson.current_source_dir(), 'bd': meson.current_build_dir(), 'tap': { + 'env': { + 'enable_injection_points': get_option('injection_points') ? 'yes' : 'no', + }, 'tests': [ 't/001_password.pl', 't/002_saslprep.pl', @@ -12,6 +15,7 @@ tests += { 't/004_file_inclusion.pl', 't/005_sspi.pl', 't/006_login_trigger.pl', + 't/007_pre_auth.pl', ], }, } diff --git a/src/test/authentication/t/007_pre_auth.pl b/src/test/authentication/t/007_pre_auth.pl new file mode 100644 index 00000000000..a638226dbaf --- /dev/null +++ b/src/test/authentication/t/007_pre_auth.pl @@ -0,0 +1,81 @@ + +# Copyright (c) 2021-2025, PostgreSQL Global Development Group + +# Tests for connection behavior prior to authentication. + +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Time::HiRes qw(usleep); +use Test::More; + +if ($ENV{enable_injection_points} ne 'yes') +{ + plan skip_all => 'Injection points not supported by this build'; +} + +my $node = PostgreSQL::Test::Cluster->new('primary'); +$node->init; +$node->append_conf( + 'postgresql.conf', q[ +log_connections = on +]); + +$node->start; + +# Check if the extension injection_points is available, as it may be +# possible that this script is run with installcheck, where the module +# would not be installed by default. +if (!$node->check_extension('injection_points')) +{ + plan skip_all => 'Extension injection_points not installed'; +} + +$node->safe_psql('postgres', 'CREATE EXTENSION injection_points'); + +# Connect to the server and inject a waitpoint. +my $psql = $node->background_psql('postgres'); +$psql->query_safe("SELECT injection_points_attach('init-pre-auth', 'wait')"); + +# From this point on, all new connections will hang during startup, just before +# authentication. Use the $psql connection handle for server interaction. +my $conn = $node->background_psql('postgres', wait => 0); + +# Wait for the connection to show up. +my $pid; +while (1) +{ + $pid = $psql->query( + "SELECT pid FROM pg_stat_activity WHERE state = 'starting';"); + last if $pid ne ""; + + usleep(100_000); +} + +note "backend $pid is authenticating"; +ok(1, 'authenticating connections are recorded in pg_stat_activity'); + +# Detach the waitpoint and wait for the connection to complete. +$psql->query_safe("SELECT injection_points_wakeup('init-pre-auth');"); +$conn->wait_connect(); + +# Make sure the pgstat entry is updated eventually. +while (1) +{ + my $state = + $psql->query("SELECT state FROM pg_stat_activity WHERE pid = $pid;"); + last if $state eq "idle"; + + note "state for backend $pid is '$state'; waiting for 'idle'..."; + usleep(100_000); +} + +ok(1, 'authenticated connections reach idle state in pg_stat_activity'); + +$psql->query_safe("SELECT injection_points_detach('init-pre-auth');"); +$psql->quit(); +$conn->quit(); + +done_testing(); |