zeek/auxil/btest/btest-bg-wait
Patrick Kelley 8fd444092b initial
2025-05-07 15:35:15 -04:00

153 lines
3.0 KiB
Bash
Executable File

#! /usr/bin/env bash
#
# Usage: btest-bg-wait [-k] <timeout>
#
# Waits until all of the background process spawned by btest-bg-run
# have finished, or the given timeout (in seconds) has been exceeded.
#
# If the timeout triggers, all remaining processed are killed. If -k
# is not given, this is considered an error and the script abort with
# error code 1. If -k is given, a timeout is not considered an error.
#
# Once all processes have finished (or were killed), the scripts
# merges their stdout and stderr. If one of them returned an error,
# this script does so as well
if [ "$1" == "-k" ]; then
timeout_ok=1
shift
else
timeout_ok=0
fi
if [ $# != 1 ]; then
echo "usage: $(basename "$0") [-k] <timeout>"
exit 1
fi
timeout=$(($1 * 100))
procs=$(cat .bgprocs)
rm -f .timeout
touch .timeout
function check_procs {
for p in $procs; do
if [ ! -e "$p/.exitcode" ]; then
return 1
fi
done
# All done.
return 0
}
function kill_procs {
for p in $procs; do
if [ ! -e "$p/.exitcode" ]; then
kill -1 "$(cat "$p/.pid")" 2>/dev/null
cat "$p"/.cmdline >>.timeout
if [ "$1" == "timeout" ]; then
touch "$p/.timeout"
fi
fi
done
sleep 1
for p in $procs; do
if [ ! -e "$p/.exitcode" ]; then
kill -9 "$(cat "$p/.pid")" 2>/dev/null
sleep 1
fi
done
}
function collect_output {
rm -f .stdout .stderr
if [ $timeout_ok != 1 ] && [ -s .timeout ]; then
{
echo "The following processes did not terminate:"
echo
cat .timeout
echo
echo "-----------"
} >>.stderr
fi
for p in $procs; do
pid=$(cat "$p/.pid")
cmdline=$(cat "$p/.cmdline")
{
printf "<<< [%s] %s\\n" "$pid" "$cmdline"
cat "$p"/.stdout
echo ">>>"
} >>.stdout
{
printf "<<< [%s] %s\\n" "$pid" "$cmdline"
cat "$p"/.stderr
echo ">>>"
} >>.stderr
done
}
trap kill_procs EXIT
while true; do
if check_procs; then
# All done.
break
fi
timeout=$((timeout - 1))
if [ $timeout -le 0 ]; then
# Timeout exceeded.
kill_procs timeout
if [ $timeout_ok == 1 ]; then
# Just continue.
break
fi
# Exit with error.
collect_output
exit 1
fi
sleep 0.01
done
trap - EXIT
# All terminated either by themselves, or with a benign timeout.
collect_output
# See if any returned an error.
result=0
for p in $procs; do
if [ -e "$p/.timeout" ]; then
# we're here because timeouts are ok, so don't mind the exit code
# if we initiated killing the process due to timeout
continue
fi
rc=$(cat "$p/.exitcode")
pid=$(cat "$p/.pid")
cmdline=$(cat "$p/.cmdline")
if [ "$rc" != 0 ]; then
echo ">>> process $pid failed with exitcode $rc: $cmdline" >>.stderr
result=1
fi
done
exit $result