Skip to content

Commit 91d3364

Browse files
ejohnstownphilljj
authored andcommitted
scripts: capture socket state on a fwd-bulk stall
When Phase 3 stops making progress, keep sampling the echoed byte count and the forward's sockets for up to 60 seconds before failing, so a CI failure shows whether the stall clears on its own (the kernel backing off a loopback retransmit) or the forward is hung. - print uname -r, then ss -tnoi for the entry, target and SSH ports every 10 seconds - list each process's state and wchan from /proc - end the failure message with "(it resumed)" or "(it hung)"
1 parent 0eb579f commit 91d3364

1 file changed

Lines changed: 55 additions & 2 deletions

File tree

‎scripts/fwd-bulk.test‎

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ echo_payload_size=0
100100
echo_pause_after=1000000
101101
echo_pause_secs=10
102102
echo_stall_limit=20
103+
# Once the phase stalls, seconds to keep sampling its sockets before failing,
104+
# and seconds between samples.
105+
echo_capture_secs=60
106+
echo_capture_step=10
103107
echo_entry_port=0
104108
echo_target_port=0
105109
# Phase 4. The second connection's payload, and seconds to wait for it.
@@ -154,6 +158,46 @@ do_dump_logs() {
154158
done
155159
}
156160

161+
# A Phase 3 stall that clears on its own is the kernel backing off a
162+
# retransmit on loopback. One that does not clear is the forward hung. Keep
163+
# sampling the byte count and the phase's sockets for a while to tell which,
164+
# and leave echo_moved at 1 if any bytes came back meanwhile.
165+
do_echo_stall_capture() {
166+
ssh_port=`cat "$echo_ready_file" 2>/dev/null`
167+
filter="( sport = :$echo_entry_port or dport = :$echo_entry_port"
168+
filter="$filter or sport = :$echo_target_port"
169+
filter="$filter or dport = :$echo_target_port"
170+
filter="$filter or sport = :$ssh_port or dport = :$ssh_port )"
171+
echo_moved=0
172+
waited=0
173+
echo "--- stall capture, kernel `uname -r` ---"
174+
while :
175+
do
176+
now=`wc -c < "$echo_received" 2>/dev/null | tr -d ' '`
177+
[ -z "$now" ] && now=0
178+
[ "$now" -ne "$got" ] && echo_moved=1
179+
echo "--- ${waited}s after the stall: echoed $now ---"
180+
command -v ss > /dev/null 2>&1 && ss -tnoi "$filter" 2>&1
181+
[ "$now" -ge "$echo_payload_size" ] && break
182+
[ "$waited" -ge "$echo_capture_secs" ] && break
183+
sleep $echo_capture_step
184+
waited=`expr $waited + $echo_capture_step`
185+
done
186+
[ -d /proc ] || return
187+
for entry in "echoserver:$echo_server_pid" "ssh:$echo_ssh_pid" \
188+
"target:$echo_target_pid" "client:$echo_client_pid"
189+
do
190+
pid=${entry#*:}
191+
if [ ! -d "/proc/$pid" ]
192+
then
193+
echo "--- ${entry%%:*} pid $pid: exited"
194+
continue
195+
fi
196+
echo "--- ${entry%%:*} pid $pid: `grep '^State' /proc/$pid/status \
197+
2>/dev/null`, wchan `cat /proc/$pid/wchan 2>/dev/null`"
198+
done
199+
}
200+
157201
do_fail() {
158202
echo "$1"
159203
do_dump_logs
@@ -509,8 +553,17 @@ do
509553
fi
510554
done
511555

512-
[ "$got" -eq "$echo_payload_size" ] \
513-
|| do_fail "two-way forward stalled: sent $echo_payload_size, echoed $got"
556+
if [ "$got" -ne "$echo_payload_size" ]
557+
then
558+
do_echo_stall_capture
559+
if [ "$echo_moved" -eq 1 ]
560+
then
561+
do_fail "two-way forward stalled: sent $echo_payload_size, echoed\
562+
$got, then $now within ${waited}s more (it resumed)"
563+
fi
564+
do_fail "two-way forward stalled: sent $echo_payload_size, echoed $got,\
565+
nothing more in ${waited}s (it hung)"
566+
fi
514567
cmp -s "$echo_payload" "$echo_received" \
515568
|| do_fail "the echoed data does not match what was sent"
516569

0 commit comments

Comments
 (0)