From 538a20ec9abab8642e0770cd52a3adeb458c7d42 Mon Sep 17 00:00:00 2001
From: nkey <mihailnikalayeu@gmail.com>
Date: Thu, 8 Jan 2026 20:25:41 +0300
Subject: [PATCH v1 1/2] Fix wait_for_idle() to properly handle
 CLOBBER_CACHE_ALWAYS builds
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

In commit e1c971945d62, the test 010_index_concurrently_upsert.pl was added with logic to handle CLOBBER_CACHE_ALWAYS builds, where a backend can hit an injection point while attaching it due to catalog cache invalidation. The wait_for_idle() function detects whether the attachment completed or the backend became stuck waiting on an injection point.

However, using the full TAP framework timeout causes the test to wait indefinitely when a backend is stuck, until the test harness terminates it. This prevents the recovery logic from executing.

Fix by reducing the timeout to half the TAP default, and adding early exit when the backend is detected waiting on an injection point. This allows the test to promptly detect stuck backends and wake them up.

Also reduce wait_for_injection_point() timeout to half the TAP default, ensuring time remains for diagnostic output if the test gets stuck.

Author: Mihail Nikalayeu <mihailnikalayeu@gmail.com>
Reviewed-by: Álvaro Herrera <alvherre@kurilemu.de>
Discussion: https://postgr.es/m/CADzfLwWOVyJygX6BFuyuhTKkJ7uw2e8OcVCDnf6iqnOFhMPE%2BA%40mail.gmail.com
---
 .../test_misc/t/010_index_concurrently_upsert.pl | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/src/test/modules/test_misc/t/010_index_concurrently_upsert.pl b/src/test/modules/test_misc/t/010_index_concurrently_upsert.pl
index 5953af11e9e..1f3dcd80886 100644
--- a/src/test/modules/test_misc/t/010_index_concurrently_upsert.pl
+++ b/src/test/modules/test_misc/t/010_index_concurrently_upsert.pl
@@ -1,5 +1,5 @@
 
-# Copyright (c) 2025, PostgreSQL Global Development Group
+# Copyright (c) 2026, PostgreSQL Global Development Group
 
 # Test INSERT ON CONFLICT DO UPDATE behavior concurrent with
 # CREATE INDEX CONCURRENTLY and REINDEX CONCURRENTLY.
@@ -793,7 +793,7 @@ done_testing();
 sub wait_for_injection_point
 {
 	my ($node, $point_name, $timeout) = @_;
-	$timeout //= $PostgreSQL::Test::Utils::timeout_default;
+	$timeout //= $PostgreSQL::Test::Utils::timeout_default / 2;
 
 	for (my $elapsed = 0; $elapsed < $timeout * 10; $elapsed++)
 	{
@@ -833,19 +833,23 @@ sub ok_injection_point
 }
 
 # Helper: Wait for a specific backend to become idle.
-# Returns true if idle, false if timeout.
+# Returns true if idle, false if waiting for injection point or timeout.
 sub wait_for_idle
 {
 	my ($node, $pid, $timeout) = @_;
-	$timeout //= $PostgreSQL::Test::Utils::timeout_default;
+	$timeout //= $PostgreSQL::Test::Utils::timeout_default / 2;
 
 	for (my $elapsed = 0; $elapsed < $timeout * 10; $elapsed++)
 	{
-		my $state = $node->safe_psql(
+		my $result = $node->safe_psql(
 			'postgres', qq[
-			SELECT state FROM pg_stat_activity WHERE pid = $pid;
+			SELECT state, wait_event_type FROM pg_stat_activity WHERE pid = $pid;
 		]);
+		my ($state, $wait_event_type) = split(/\|/, $result, 2);
+		$state //= '';
+		$wait_event_type //= '';
 		return 1 if $state eq 'idle';
+		return 0 if $wait_event_type eq 'InjectionPoint';
 		sleep(0.1);
 	}
 	return 0;
-- 
2.43.0

