[PATCH stalld 12/36] tests/helpers: Rewrite wait_for_log_message() with process substitution

Wander Lairson Costa <[email protected]>
Newsgroups org.kernel.vger.linux-rt-users
Message-ID <[email protected]>
wait_for_log_message() uses a 1-second polling loop to check for
a pattern in a log file, adding up to 1 second of latency even
when the message appears instantly. It also has a journalctl
fallback that is unused by any caller and a misleading default
log file parameter (/var/log/syslog).

Rewrite the function to use process substitution instead of polling.
By feeding the output of a timeout-wrapped tail -f into grep -m1 -q
via process substitution, the function returns immediately when the
pattern appears. Process substitution is specifically required here
rather than a standard pipeline. In a pipeline, bash waits for both
processes to exit. Because tail -f blocks on inotify and does not
receive SIGPIPE, a pipeline would hang for the full timeout duration
even after grep finds a match.

Additionally, remove the unused journalctl fallback and make the log
file a required parameter since all callers pass one explicitly.

Signed-off-by: Wander Lairson Costa <[email protected]>
---
 tests/helpers/test_helpers.sh | 41 +++++++++++++++--------------------
 1 file changed, 18 insertions(+), 23 deletions(-)

diff --git a/tests/helpers/test_helpers.sh b/tests/helpers/test_helpers.sh
index 8ff1b80..08838a2 100755
--- a/tests/helpers/test_helpers.sh
+++ b/tests/helpers/test_helpers.sh
@@ -500,36 +500,31 @@ handle_signal() {
 trap cleanup EXIT
 trap handle_signal INT TERM
 
-# Parse stalld log for specific message
+# Wait for a specific message to appear in a log file.
+# Uses tail -f piped through grep for instant detection -- returns
+# immediately when the pattern appears instead of sleeping between
+# polling intervals. Replays existing file content so messages
+# written before this function is called are also matched.
+#
+# Usage: wait_for_log_message <pattern> <timeout> <log_file>
 wait_for_log_message() {
 	local pattern=$1
 	local timeout=${2:-10}
-	local log_file=${3:-/var/log/syslog}
+	local log_file=$3
 
-	# If log_file doesn't exist, try journalctl
-	if [ ! -f "${log_file}" ]; then
-		# Using journalctl instead
-		local elapsed=0
-		while [ ${elapsed} -lt ${timeout} ]; do
-			if journalctl -u stalld --since "1 minute ago" 2>/dev/null | grep -q "${pattern}"; then
-				return 0
-			fi
-			sleep 1
-			elapsed=$((elapsed + 1))
-		done
+	if [ -z "${log_file}" ]; then
+		echo -e "${RED}ERROR: wait_for_log_message requires a log file${NC}"
 		return 1
 	fi
 
-	local elapsed=0
-	while [ ${elapsed} -lt ${timeout} ]; do
-		if grep -q "${pattern}" "${log_file}"; then
-			return 0
-		fi
-		sleep 1
-		elapsed=$((elapsed + 1))
-	done
-
-	return 1
+	# Process substitution runs tail in the background so bash
+	# only waits for grep to finish. A pipeline (tail | grep)
+	# would block until timeout kills tail even after grep has
+	# matched, because tail -f is blocked on inotify and never
+	# receives SIGPIPE.
+	grep -m1 -q "${pattern}" \
+		< <(timeout "${timeout}" tail -f -n +1 "${log_file}" 2>/dev/null)
+	return $?
 }
 
 # Get thread scheduling policy
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.