mirror of https://github.com/wolfSSL/wolfssh.git
wolfsshd: wait for the listener, claim the ports
start_wolfsshd returns once the daemon accepts connections, not once it has written its pid: wolfSSHd saves the PID file just before tcp_listen(), so a caller connecting straight away could be refused while the daemon's log showed no connection at all. A run also claims its port block rather than only probing it. - wait for the daemon's own "Listening on port" line, matched on its pid so a previous daemon's line in the appended log cannot satisfy it - take a block by creating its lock directory, which mkdir makes atomic, and release it in the teardown; probing alone let two runners pick the same block, and a claim whose owner is gone is treated as stale - check that a pid from the PID file is still a wolfsshd, since kill -0 answers only whether some process owns the number - fail the OpenSSH cert test when mktemp gives it no work dir: an empty one reduced its teardown pattern to every wolfsshd presentpull/1256/head
parent
ac532af87f
commit
347046f8fd
|
|
@ -96,12 +96,45 @@ port_in_use() {
|
|||
(exec 3<>"/dev/tcp/127.0.0.1/$1") 2>/dev/null
|
||||
}
|
||||
|
||||
# Where blocks are claimed. Sticky and world-writable like /tmp itself, so a
|
||||
# run as the invoking user and a run under sudo can claim from the same pool.
|
||||
PORT_LOCK_ROOT="${TMPDIR:-/tmp}/wolfssh-sshd-ports"
|
||||
mkdir -p "$PORT_LOCK_ROOT" 2>/dev/null
|
||||
chmod 1777 "$PORT_LOCK_ROOT" 2>/dev/null || true
|
||||
|
||||
# Take a block by creating its directory. mkdir is atomic, so of two runners
|
||||
# racing for one block exactly one wins; probing alone could not do this,
|
||||
# because both could see the same eight ports free before either had bound
|
||||
# one. The claim is held for the whole run and released in run_teardown.
|
||||
claim_port_block() {
|
||||
local lock owner
|
||||
lock="$PORT_LOCK_ROOT/$1"
|
||||
if mkdir "$lock" 2>/dev/null; then
|
||||
echo $$ > "$lock/pid" 2>/dev/null
|
||||
return 0
|
||||
fi
|
||||
# A claim whose owner is gone is stale. Without this a run killed before
|
||||
# its teardown would take its block out of circulation permanently. Two
|
||||
# runners can reach this at once; the loser's mkdir just fails and it
|
||||
# moves on to the next block.
|
||||
owner=`cat "$lock/pid" 2>/dev/null`
|
||||
if [ -n "$owner" ] && ! kill -0 "$owner" 2>/dev/null; then
|
||||
rm -rf "$lock" 2>/dev/null
|
||||
if mkdir "$lock" 2>/dev/null; then
|
||||
echo $$ > "$lock/pid" 2>/dev/null
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
find_port_block() {
|
||||
local start i n base busy
|
||||
start=$(( $$ % PORT_BLOCK_COUNT ))
|
||||
for (( i = 0; i < PORT_BLOCK_COUNT; i++ )); do
|
||||
base=$(( PORT_BLOCK_FIRST \
|
||||
+ ((start + i) % PORT_BLOCK_COUNT) * PORT_BLOCK_SIZE ))
|
||||
claim_port_block "$base" || continue
|
||||
busy=0
|
||||
for (( n = 0; n < PORT_BLOCK_SIZE; n++ )); do
|
||||
if port_in_use $(( base + n )); then
|
||||
|
|
@ -113,11 +146,15 @@ find_port_block() {
|
|||
printf '%s' "$base"
|
||||
return 0
|
||||
fi
|
||||
# Claimed but unusable: something outside the suite holds a port in
|
||||
# it. Give the claim back rather than sit on a block we cannot use.
|
||||
rm -rf "$PORT_LOCK_ROOT/$base" 2>/dev/null
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
PORT_BASE=`find_port_block`
|
||||
PORT_LOCK_DIR="$PORT_LOCK_ROOT/$PORT_BASE"
|
||||
if [ -z "$PORT_BASE" ]; then
|
||||
echo "Error: no free block of $PORT_BLOCK_SIZE ports found starting at" \
|
||||
"$PORT_BLOCK_FIRST."
|
||||
|
|
@ -171,6 +208,9 @@ run_teardown() {
|
|||
stop_all_wolfsshd || true
|
||||
fi
|
||||
rm -f "$WOLFSSHD_TEST_PIDFILE" || true
|
||||
if [ -n "$PORT_BASE" ]; then
|
||||
rm -rf "$PORT_LOCK_DIR" || true
|
||||
fi
|
||||
}
|
||||
trap run_teardown EXIT
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,13 @@ command -v ssh-keygen >/dev/null 2>&1 || \
|
|||
skip "ssh-keygen not found, skipping OpenSSH cert test"
|
||||
|
||||
WORK=$(mktemp -d)
|
||||
# Checked before the trap below is installed: an empty WORK would reduce its
|
||||
# pattern to "wolfsshd .*", which matches every wolfsshd on the machine and is
|
||||
# exactly the host-wide teardown this suite no longer does.
|
||||
if [ -z "$WORK" ] || [ ! -d "$WORK" ]; then
|
||||
echo "FAIL: could not create a work directory for the OpenSSH cert test"
|
||||
exit 1
|
||||
fi
|
||||
# Matched on $WORK, this run's own mktemp dir, not on the config basename:
|
||||
# "sshd_config_ossh" appears in every concurrent run's command line too,
|
||||
# so the basename pattern tore down another run's daemon along with this
|
||||
|
|
|
|||
|
|
@ -134,8 +134,10 @@ EOF
|
|||
sleep 0.1
|
||||
done
|
||||
# A pid file left by a daemon that has since died is worse than none:
|
||||
# stop_wolfsshd would kill whatever has been given that pid since.
|
||||
if [ -n "$PID" ] && ! sudo kill -0 "$PID" 2>/dev/null; then
|
||||
# stop_wolfsshd would kill whatever has been given that pid since. Ask
|
||||
# what the process is, not merely whether it exists: "kill -0" answers
|
||||
# the second question only, and the pid may have been recycled.
|
||||
if [ -n "$PID" ] && ! pgrep -x wolfsshd | grep -qx -- "$PID"; then
|
||||
PID=""
|
||||
fi
|
||||
else
|
||||
|
|
@ -157,6 +159,22 @@ EOF
|
|||
sleep 0.1
|
||||
done
|
||||
fi
|
||||
# wolfSSHd writes its PID file in StartSSHD() immediately before
|
||||
# tcp_listen(), so the pid appearing does not mean the socket accepts yet.
|
||||
# A caller that connects the moment this returns -- several do, with no
|
||||
# sleep -- would be refused, and the daemon's log would show no connection
|
||||
# at all. Wait for the daemon's own listening line, matched on its pid so
|
||||
# that a previous daemon's line in this appended log cannot satisfy it.
|
||||
if [ -n "$PID" ]; then
|
||||
for i in $(seq 1 100); do
|
||||
if sudo grep -qF "[PID $PID]: [SSHD] Listening on port" \
|
||||
./log.txt 2>/dev/null; then
|
||||
break
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
fi
|
||||
|
||||
printf "SSHD running on PID $PID\n"
|
||||
|
||||
# Record the daemon in the run's registry, if the runner set one up. Test
|
||||
|
|
|
|||
Loading…
Reference in New Issue