syncevolution/test/wrappercheck.sh

137 lines
3.9 KiB
Bash
Executable File

#! /bin/bash
#
# wrappercheck.sh background command args ... -- command args ...
#
# Wrapper script which runs one command in the background and the
# other in the foreground. Once that second command completes, the
# first one is send a SIGINT+SIGTERM, then a SIGKILL until it terminates.
#
# Overall return code of this script is the return code of the
# foreground command or, if that is 0, the background command.
set -e
set -x
PS4='wrappercheck-$$ line ${LINENO}: '
PIDS=
trap "[ \"$PIDS\" ] && kill -TERM $PIDS" TERM
trap "[ \"$PIDS\" ] && kill -INT $PIDS" INT
DAEMON_LOG=
WAIT_FOR_DAEMON_OUTPUT=
WAIT_FOR_DBUS_DAEMON=
declare -a BACKGROUND
declare -a ENV
# parse parameters
while [ $# -gt 1 ] && [ "$1" != "--" ] ; do
case "$1" in
--daemon-log)
shift
DAEMON_LOG="$1"
;;
--wait-for-dbus-daemon)
shift
WAIT_FOR_DBUS_DAEMON="$1"
;;
--wait-for-daemon-output)
shift
WAIT_FOR_DAEMON_OUTPUT="$1"
;;
--daemon-sleep)
shift
DAEMON_SLEEP="$1"
;;
*=*)
ENV[${#ENV[*]}]="$1"
;;
*)
break
;;
esac
shift
done
# gather command and its parameters
while [ $# -gt 1 ] && [ "$1" != "--" ] ; do
BACKGROUND[${#BACKGROUND[*]}]="$1"
shift
done
shift
if [ "$DAEMON_LOG" ] && [ "$WAIT_FOR_DAEMON_OUTPUT" ]; then
daemonmatches=$(grep -e "$WAIT_FOR_DAEMON_OUTPUT" "$DAEMON_LOG" | wc -l)
fi
( set +x; echo >&2 "*** starting ${BACKGROUND[0]} as background daemon, output to ${DAEMON_LOG:-stderr}" )
# We need to create a process group so that we can kill all processes started by the sub-shell.
# ${BACKGROUND[*]} is used instead of ${BACKGROUND[@]} because although the later should have
# avoided expansion of words (good!) somehow the quoting got messed up in practice (bad!).
( set -x; exec >>${DAEMON_LOG:-&2} 2>&1; exec env "${ENV[@]}" setsid /bin/bash -c "set -x -o pipefail; ${BACKGROUND[*]} 2>&1 | $(dirname $0)/logger.py" ) &
BACKGROUND_PID=$!
PIDS+="$BACKGROUND_PID"
if [ "$DAEMON_LOG" ] && [ "$WAIT_FOR_DAEMON_OUTPUT" ]; then
( set +x; echo >&2 "*** waiting for daemon to write '$WAIT_FOR_DAEMON_OUTPUT' into $DAEMON_LOG"
while kill -0 $BACKGROUND_PID 2>/dev/null &&
[ $daemonmatches -eq $(grep -e "$WAIT_FOR_DAEMON_OUTPUT" "$DAEMON_LOG" | wc -l) ]; do
sleep 1
done
)
fi
if [ "$WAIT_FOR_DBUS_DAEMON" ]; then
( set +x; echo >&2 "*** waiting for daemon to connect to D-Bus as '$WAIT_FOR_DBUS_DAEMON'"
while kill -0 $BACKGROUND_PID 2>/dev/null &&
! (dbus-send --session --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListNames | grep -q "$WAIT_FOR_DBUS_DAEMON"); do
sleep 1
done
)
fi
if kill -0 $BACKGROUND_PID 2>/dev/null; then
set +e
if [ "$DAEMON_SLEEP" ]; then
( set +x; echo >&2 "*** 'sleep $DAEMON_SLEEP' for daemon to settle down" )
sleep $DAEMON_SLEEP
fi
(set -x; "$@")
RET=$?
set -e
else
echo >&2 "*** ${BACKGROUND[0]} terminated prematurely"
RET=1
fi
( set +x; echo >&2 "*** killing and waiting for ${BACKGROUND[0]}" )
if kill -INT -$BACKGROUND_PID >&2 && kill -TERM -$BACKGROUND_PID >&2 || kill -INT $BACKGROUND_PID >&2 && kill -TERM $BACKGROUND_PID >&2; then
perl -e "sleep(60); kill(9, -$BACKGROUND_PID);" &
KILL_PID=$!
else
ps x --forest >&2
KILL_PID=
fi
set +e
wait $BACKGROUND_PID
SUBRET=$?
case $SUBRET in 0|130|137|139|143) SUBRET=0;; # 130 and 143 indicate that it was killed, probably by us, which is okay
esac
SUBRET=0 # TODO: don't ignore daemon results
if [ "$KILL_PID" ]; then
msg=$(LC_ALL=C kill -KILL $KILL_PID 2>&1)
if echo "$msg" | grep -q 'No such process'; then
# Consider this a success.
SUBRET=0
else
echo "$msg"
fi
wait $KILL_PID
fi
set -e
if [ $RET = 0 ]; then
RET=$SUBRET
fi
exit $RET