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