Fix race condition in TAP test 007_pre_auth
authorMichael Paquier <[email protected]>
Thu, 6 Mar 2025 23:12:45 +0000 (08:12 +0900)
committerMichael Paquier <[email protected]>
Thu, 6 Mar 2025 23:12:45 +0000 (08:12 +0900)
The authentication test added in c76db55c9085 expects a backend to start
and wait at the injection point "init-pre-auth".  A query is used to
retrieve the PID of the backend waiting at authentication, but its WHERE
clause was too soft, checking only for a backend in a "starting" state.

As proved by the CI, this WHERE clause is not enough.  There is a small
window between the moment when the backend is reported as "starting" in
its backend entry and the moment when it waits in its injection point,
and it was possible for the test to return the PID of a backend process
not yet waiting in the injection point, causing spurious failures.  This
issue is fixed by tweaking the query retrieving the PID of the backend
waiting before authentication so as we check for "init-pre-auth" in its
wait_event.  An extra check based on the backend_type is added, based on
a suggestion by Jacob, to be more cautious.

Error spotted by the CI on Windows, but it could happen anywhere, as
long as the authentication path is slow enough compared to the TAP test.

Reported-by: Andres Freund <[email protected]>
Author: Jacob Champion <[email protected]>
Co-authored-by: Michael Paquier <[email protected]>
Discussion: https://postgr.es/m/soexrl7oeyku24bj3czupxmv27ow35u6edymp5y3oyoysbe2kb@r3tgoos2xp2x

src/test/authentication/t/007_pre_auth.pl

index a638226dbaf11b66ab5dcab74b8b332295577484..12e40dc722c931f245dfaa6bb92e88eb2752e153 100644 (file)
@@ -43,12 +43,16 @@ $psql->query_safe("SELECT injection_points_attach('init-pre-auth', 'wait')");
 # authentication. Use the $psql connection handle for server interaction.
 my $conn = $node->background_psql('postgres', wait => 0);
 
-# Wait for the connection to show up.
+# Wait for the connection to show up in pg_stat_activity, with the wait_event
+# of the injection point.
 my $pid;
 while (1)
 {
    $pid = $psql->query(
-       "SELECT pid FROM pg_stat_activity WHERE state = 'starting';");
+       qq{SELECT pid FROM pg_stat_activity
+  WHERE backend_type = 'client backend'
+    AND state = 'starting'
+    AND wait_event = 'init-pre-auth';});
    last if $pid ne "";
 
    usleep(100_000);