Compare commits
9 Commits
03f1ba07c7
...
f286c141b3
Author | SHA1 | Date | |
---|---|---|---|
f286c141b3 | |||
0c009f55fe | |||
670a83948d | |||
62c31095c9 | |||
55aa8dbc6f | |||
e4dab9f13b | |||
373db13c20 | |||
67ff44f4ed | |||
849a02481d |
54
all-full-example.sh
Executable file
54
all-full-example.sh
Executable file
|
@ -0,0 +1,54 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# From https://stackoverflow.com/a/360275
|
||||||
|
kill_child_jobs() {
|
||||||
|
echo "In kill_child_jobs()..."
|
||||||
|
# Workaround for https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=482999
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
jobs -p > "$tmp"
|
||||||
|
child_pids=$(cat "$tmp")
|
||||||
|
for child in $child_pids
|
||||||
|
do
|
||||||
|
# From https://unix.stackexchange.com/a/574169
|
||||||
|
if [ -n "${child##*[!0-9]*}" ]
|
||||||
|
then
|
||||||
|
echo Killing "$child"
|
||||||
|
# From https://stackoverflow.com/a/11231970
|
||||||
|
kill "$child" || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# zsh version from https://stackoverflow.com/a/36354483
|
||||||
|
# zsh doesn't have jobs -p
|
||||||
|
jobs > "$tmp"
|
||||||
|
cat "$tmp"
|
||||||
|
<"$tmp" sed --regexp-extended --quiet 's/\[([[:digit:]]+)\].*running.*/%\1/gp' | while read -r child
|
||||||
|
do
|
||||||
|
echo Killing job "$child"
|
||||||
|
kill "$child" || true
|
||||||
|
done
|
||||||
|
|
||||||
|
rm "$tmp"
|
||||||
|
}
|
||||||
|
cleanup() {
|
||||||
|
kill_child_jobs
|
||||||
|
}
|
||||||
|
|
||||||
|
#trap "kill_child_jobs" INT TERM QUIT
|
||||||
|
#trap date INT TERM QUIT
|
||||||
|
|
||||||
|
# From https://unix.stackexchange.com/a/240736
|
||||||
|
for sig in INT QUIT HUP TERM ALRM USR1; do
|
||||||
|
trap "
|
||||||
|
cleanup
|
||||||
|
trap - $sig EXIT
|
||||||
|
kill -s $sig "'"$$"' "$sig"
|
||||||
|
done
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
yes aa &
|
||||||
|
yes b &
|
||||||
|
sleep 100 &
|
||||||
|
|
||||||
|
wait
|
33
all.sh
Executable file
33
all.sh
Executable file
|
@ -0,0 +1,33 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# From https://stackoverflow.com/a/360275
|
||||||
|
kill_child_jobs() {
|
||||||
|
echo "In kill_child_jobs()..."
|
||||||
|
# Workaround for https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=482999
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
jobs -p > "$tmp"
|
||||||
|
child_pids=$(cat "$tmp")
|
||||||
|
for child in $child_pids
|
||||||
|
do
|
||||||
|
# From https://unix.stackexchange.com/a/574169
|
||||||
|
if [ -n "${child##*[!0-9]*}" ]
|
||||||
|
then
|
||||||
|
echo Killing "$child"
|
||||||
|
# From https://stackoverflow.com/a/11231970
|
||||||
|
kill "$child" || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# zsh version from https://stackoverflow.com/a/36354483
|
||||||
|
# zsh doesn't have jobs -p
|
||||||
|
jobs > "$tmp"
|
||||||
|
cat "$tmp"
|
||||||
|
<"$tmp" sed --regexp-extended --quiet 's/\[([[:digit:]]+)\].*running.*/%\1/gp' | while read -r child
|
||||||
|
do
|
||||||
|
echo Killing job "$child"
|
||||||
|
kill "$child" || true
|
||||||
|
done
|
||||||
|
|
||||||
|
rm "$tmp"
|
||||||
|
}
|
4
noop.sh
Executable file
4
noop.sh
Executable file
|
@ -0,0 +1,4 @@
|
||||||
|
kill_child_jobs() {
|
||||||
|
# Do nothing to show what test script does when jobs are not killed.
|
||||||
|
:
|
||||||
|
}
|
6
pkill-P.sh
Executable file
6
pkill-P.sh
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
kill_child_jobs() {
|
||||||
|
echo "In kill_child_jobs()..."
|
||||||
|
# From https://stackoverflow.com/a/23336595
|
||||||
|
# Kills all child proceses, not just jobs.
|
||||||
|
pkill -P $$
|
||||||
|
}
|
16
test/make-and-kill-child-jobs.sh
Executable file
16
test/make-and-kill-child-jobs.sh
Executable file
|
@ -0,0 +1,16 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
DIR=$(dirname "$0")
|
||||||
|
|
||||||
|
. "$1"
|
||||||
|
|
||||||
|
# Set up child jobs
|
||||||
|
|
||||||
|
"$DIR/wait_for_pid_exit.sh" job $$ &
|
||||||
|
"$DIR/wait_for_pid_exit.sh" disowned $$ &
|
||||||
|
builtin disown || echo "shell does not support disown"
|
||||||
|
|
||||||
|
# Wait for jobs to actually start.
|
||||||
|
sleep 0.01s
|
||||||
|
|
||||||
|
kill_child_jobs
|
44
test/test-all.sh
Executable file
44
test/test-all.sh
Executable file
|
@ -0,0 +1,44 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
DIR="$(dirname "$0")"
|
||||||
|
SHELLS="bash sh ash dash zsh ksh"
|
||||||
|
|
||||||
|
echo "Legend:"
|
||||||
|
echo " ∞=script does not halt (after 1 second timeout)"
|
||||||
|
echo " X=disown unsupported by shell"
|
||||||
|
echo " ☠=all children killed"
|
||||||
|
echo " 🏃=all children still running"
|
||||||
|
echo
|
||||||
|
|
||||||
|
printf '\t'
|
||||||
|
for shell in $SHELLS
|
||||||
|
do
|
||||||
|
if ! command -v "$shell" >/dev/null
|
||||||
|
then
|
||||||
|
>&2 echo "Shell $shell not found."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
printf '\t%s' "$shell"
|
||||||
|
done
|
||||||
|
printf '\n'
|
||||||
|
|
||||||
|
for script in "$DIR"/../*.sh
|
||||||
|
do
|
||||||
|
if [ -x "$script" ] && grep -qF 'kill_child_jobs()' "$script" && ! grep -qF 'wait' "$script"
|
||||||
|
then
|
||||||
|
name="$(basename "$script")"
|
||||||
|
printf '%s' "$name"
|
||||||
|
if [ ${#name} -lt 8 ]
|
||||||
|
then
|
||||||
|
printf '\t'
|
||||||
|
fi
|
||||||
|
|
||||||
|
for shell in $SHELLS
|
||||||
|
do
|
||||||
|
printf '\t'
|
||||||
|
"$DIR/test-kill-child-jobs.sh" "$script" "$shell" || true
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
printf '\n'
|
||||||
|
done
|
72
test/test-kill-child-jobs.sh
Executable file
72
test/test-kill-child-jobs.sh
Executable file
|
@ -0,0 +1,72 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
DIR="$(dirname "$0")"
|
||||||
|
|
||||||
|
SCRIPT="$1"
|
||||||
|
SHELL="$2"
|
||||||
|
|
||||||
|
if [ ! -x "$SCRIPT" ]
|
||||||
|
then
|
||||||
|
>&2 echo "First argument should be file with kill_child_jobs() function to test."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v "$SHELL" >/dev/null
|
||||||
|
then
|
||||||
|
>&2 echo "Second argument should be shell to test."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
TMP="$(mktemp)"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# timeout code from https://stackoverflow.com/a/10028986
|
||||||
|
pidFile="$(mktemp)"
|
||||||
|
(
|
||||||
|
"$SHELL" "$DIR/make-and-kill-child-jobs.sh" "$SCRIPT" >"$TMP" 2>&1 || true
|
||||||
|
rm "$pidFile"
|
||||||
|
) &
|
||||||
|
pid=$!
|
||||||
|
echo $pid > "$pidFile"
|
||||||
|
(
|
||||||
|
sleep 1
|
||||||
|
if [ -e "$pidFile" ]
|
||||||
|
then
|
||||||
|
pkill -P $pid
|
||||||
|
printf '∞'
|
||||||
|
fi
|
||||||
|
) &
|
||||||
|
killerPid=$!
|
||||||
|
|
||||||
|
wait $pid
|
||||||
|
kill $killerPid 2>/dev/null || true
|
||||||
|
rm -f "$pidFile" || true
|
||||||
|
|
||||||
|
# Make sure we've waited long enough for the "outlived" messages to be generated.
|
||||||
|
sleep 0.1s
|
||||||
|
|
||||||
|
if grep -q '^shell does not support disown$' "$TMP"
|
||||||
|
then
|
||||||
|
printf "X"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! grep -q '^disowned outlived parent.$' "$TMP"
|
||||||
|
then
|
||||||
|
# disowned should have outlived parent
|
||||||
|
EXITCODE=2
|
||||||
|
printf "☠"
|
||||||
|
elif grep -q '^job outlived parent.$' "$TMP"
|
||||||
|
then
|
||||||
|
# job should not outlive parent
|
||||||
|
EXITCODE=3
|
||||||
|
printf "🏃"
|
||||||
|
else
|
||||||
|
# all good
|
||||||
|
EXITCODE=0
|
||||||
|
printf '%s' "$SHELL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f "$TMP"
|
||||||
|
exit $EXITCODE
|
8
test/wait_for_pid_exit.sh
Executable file
8
test/wait_for_pid_exit.sh
Executable file
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "Starting child $1..."
|
||||||
|
while kill -0 "$2" 2>/dev/null
|
||||||
|
do
|
||||||
|
sleep 0.01s
|
||||||
|
done
|
||||||
|
echo "$1 outlived parent."
|
28
zsh.sh
Executable file
28
zsh.sh
Executable file
|
@ -0,0 +1,28 @@
|
||||||
|
#!/bin/zsh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# From https://stackoverflow.com/a/360275
|
||||||
|
kill_child_jobs() {
|
||||||
|
echo "In kill_child_jobs()..."
|
||||||
|
|
||||||
|
# From https://unix.stackexchange.com/a/544167
|
||||||
|
while kill %% >/dev/null; do :; done
|
||||||
|
}
|
||||||
|
cleanup() {
|
||||||
|
kill_child_jobs
|
||||||
|
}
|
||||||
|
|
||||||
|
# From https://unix.stackexchange.com/a/240736
|
||||||
|
for sig in INT QUIT HUP TERM ALRM USR1; do
|
||||||
|
trap "
|
||||||
|
cleanup
|
||||||
|
trap - $sig EXIT
|
||||||
|
kill -s $sig "'"$$"' "$sig"
|
||||||
|
done
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
yes aa &
|
||||||
|
yes b &
|
||||||
|
sleep 100 &
|
||||||
|
|
||||||
|
wait
|
Loading…
Reference in New Issue
Block a user