mirror of
https://github.com/isc-projects/bind9.git
synced 2026-07-15 01:00:57 -04:00
fix: test: Retry pipequeries on a transient EADDRINUSE in the pipelined test
On FreeBSD, the TCP connect() call can transiently fail with EADDRINUSE under parallel CI load. The netmgr already retries such connects (see #3451), but it retries on the same socket, which is already bound to the same ephemeral source port, so when the four-tuple is genuinely busy (e.g. in TIME_WAIT) every retry fails the same way. pipequeries then exits with "request event result: address in use", leaving raw.1 empty and failing the first check. All eight requests share a single TCP dispatch, so the failed connect means no query ever reached ns4 and its cache is still cold. It is therefore safe to run pipequeries again: a fresh process binds a new ephemeral port, and the out-of-order check keeps its meaning. Retry for up to ten attempts, but only on this specific transient error. Assisted-by: Claude Code:claude-fable-5 Merge branch 'mnowak/pipelined-retry-transient-eaddrinuse' into 'main' See merge request isc-projects/bind9!12228
This commit is contained in:
commit
28cddaaba6
2 changed files with 27 additions and 1 deletions
|
|
@ -32,7 +32,32 @@ n=1
|
|||
ret=0
|
||||
|
||||
echo_i "check pipelined TCP queries ($n)"
|
||||
pipequeries <input >raw.$n || ret=1
|
||||
# On FreeBSD, the TCP connect() call can transiently fail with
|
||||
# EADDRINUSE even after the netmgr retried it in place: the socket is
|
||||
# already bound, so retrying on the same source port cannot help.
|
||||
# pipequeries then bails out before any query is sent, which leaves
|
||||
# the ns4 cache cold, so it is safe to simply run it again (and the
|
||||
# out-of-order check below remains meaningful on a repeated run).
|
||||
#
|
||||
# This loop is a workaround for the pipequeries.c implementation. If
|
||||
# pipequeries is ever rewritten in pure Python (using the test suite's
|
||||
# own DNS machinery, which can pick a fresh source port per attempt),
|
||||
# this retry should no longer be necessary and can be dropped.
|
||||
pq_left=10
|
||||
while :; do
|
||||
ret=0
|
||||
pipequeries <input >raw.$n 2>pipequeries.err.$n || ret=1
|
||||
cat pipequeries.err.$n >&2
|
||||
pq_left=$((pq_left - 1))
|
||||
if [ $ret -eq 0 ] || [ $pq_left -le 0 ]; then
|
||||
break
|
||||
fi
|
||||
if ! grep "address in use" pipequeries.err.$n >/dev/null; then
|
||||
break
|
||||
fi
|
||||
echo_i "retrying pipequeries after a transient connect failure"
|
||||
sleep 1
|
||||
done
|
||||
awk '{ print $1 " " $5 }' <raw.$n >output.$n
|
||||
sort <output.$n >output-sorted.$n
|
||||
diff ref output-sorted.$n || {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import pytest
|
|||
pytestmark = pytest.mark.extra_artifacts(
|
||||
[
|
||||
"output*",
|
||||
"pipequeries.err*",
|
||||
"raw*",
|
||||
"ans*/ans.run",
|
||||
]
|
||||
|
|
|
|||
Loading…
Reference in a new issue