name: "Builtins: kill" cases: - name: "kill -l" ignore_stderr: true stdin: | for i in $(seq 1 31); do kill -l $i; done # limit the number of signals to 31. Realtime signals are not implemented yet. for i in $(kill -l | sed -e "s/[[:digit:]]*)//g"); do echo $i; done | head -31 # invalid option kill -l 9999 kill -l HUP kill -l iNt kill -l int kill -l SIGHUP kill -l EXIT - name: "kill -s" stdin: | kill -s USR1 $$ - name: "kill -n" stdin: | kill -n 9 $$ - name: "kill -s with its signal attached" stdin: | kill -sUSR1 $$ - name: "kill -n with its signal attached" stdin: | kill -n15 $$ - name: "kill -SIGNAME" stdin: | kill -HUP $$ - name: "kill -s SIG -- pid" stdin: | kill -s HUP -- $$ - name: "kill -SIG -- pid" known_failure: true # TODO(kill): `--` after -SIG is taken for a pid stdin: | kill -9 -- $$ - name: "kill -n 0" stdin: | kill -n $((5-5)) $$ echo OK - name: "A shell ignores SIGQUIT, even when not interactive" known_failure: true # TODO(signals): bash ignores SIGQUIT in all cases, but a brush that isn't interactive takes its default action stdin: | "$BASH" -c 'kill -QUIT $$; echo survived' echo "status: $?" - name: "A program that a signal ends is reported" known_failure: true # TODO(jobs): brush reports nothing when a signal other than SIGINT or SIGPIPE ends a program, as bash does on stderr stdin: | sh -c 'kill -TERM $$' echo "status: $?" - name: "An interactive shell without a terminal survives SIGTERM" known_failure: true # TODO(signals): brush has an interactive shell survive signals only once it takes a terminal stdin: | echo 'kill -TERM $$; echo survived' | "$BASH" --norc --noprofile -i 2>/dev/null echo "status: $?" - name: "kill -sigspec" stdin: | kill -USR1 $$ - name: "kill -sigspec (numeric)" stdin: | kill -9 $$ - name: "kill -0 (numeric)" stdin: | kill -0000 $$ echo OK - name: "kill -0 (numeric, non-existent)" ignore_stderr: true stdin: | kill -0 99999999 - name: "kill continues a stopped job sent SIGTERM, so it can act on it" ignore_stderr: true stdin: | set -m sh -c 'trap "echo terminated >status.txt; exit 3" TERM; kill -STOP $$; echo resumed' kill -TERM %1 for i in $(seq 100); do [ -s status.txt ] && break; sleep 0.1; done cat status.txt rm -f status.txt - name: "kill continues a job sent SIGTERM that stopped again in the background" ignore_stderr: true stdin: | set -m sh -c 'echo $$ >pid.txt; trap "echo terminated >status.txt; exit 3" TERM; kill -STOP $$; kill -STOP $$' bg >/dev/null for i in $(seq 100); do case $(ps -o stat= -p "$(cat pid.txt)") in T*) break ;; esac; sleep 0.1; done kill -TERM %1 for i in $(seq 100); do [ -s status.txt ] && break; sleep 0.1; done cat status.txt rm -f pid.txt status.txt - name: "A stopped job that survives SIGTERM runs on" ignore_stderr: true stdin: | set -m sh -c 'trap "echo caught >status.txt" TERM; kill -STOP $$; while [ ! -e done.txt ]; do sleep 0.1; done' kill -TERM %1 for i in $(seq 100); do [ -s status.txt ] && break; sleep 0.1; done cat status.txt jobs -r >running.txt; echo "running: $(( $(wc -l stopped.txt; echo "stopped: $(( $(wc -l pidfile; while :; do sleep 0.05; done' & while [ ! -s pidfile ]; do sleep 0.05; done kill "$(cat pidfile)" wait # The process ID differs from run to run. rm pidfile - name: "kill takes -- before a process group, and -s 0" known_failure: true # TODO(signals): kill's default signal and option parsing ignore_stderr: true stdin: | kill -0 -- $$; echo "a=$?" kill -s 0 $$; echo "b=$?" kill -0 -- -$(ps -o pgid= -p $$ | tr -d ' '); echo "c=$?" # An exited process's ID names no process or group, so nothing else is signaled. dead=$(sh -c 'echo $$') kill -- -$dead; echo "d=$?" kill -s TERM -- -$dead; echo "e=$?" - name: "kill takes -N after a signal as a process group" known_failure: true # TODO(kill): -N after a signal is taken for an invalid signal ignore_stderr: true stdin: | # Signal 0 checks this shell's own group without signaling it. kill -0 -$(ps -o pgid= -p $$ | tr -d ' '); echo "a=$?" # An exited process's ID names no process or group, so nothing else is # signaled; only the reason kill gives for failing is compared. dead=$(sh -c 'echo $$') kill -TERM -$dead 2>&1 | grep -c 'invalid signal'; echo "b=${PIPESTATUS[0]}" - name: "kill takes -N alone as a signal number" ignore_stderr: true stdin: | # -999999 is an invalid signal number here, not a target. kill -999999 2>&1 | grep -c 'invalid signal'; echo "rc=${PIPESTATUS[0]}" - name: "kill takes the words after its first operand as operands" ignore_stderr: true stdin: | kill -0 $$ -l || true echo "done" - name: "kill takes its signal in each form" ignore_stderr: true stdin: | kill -l -- 9 kill -l HUP # An exited process's ID names no process or group, so nothing else is # signaled; only the reason kill gives for failing is compared. dead=$(sh -c 'echo $$') kill -sUSR1 $dead 2>&1 | grep -c 'invalid signal'; echo "a=${PIPESTATUS[0]}" kill -n9 $dead 2>&1 | grep -c 'invalid signal'; echo "b=${PIPESTATUS[0]}" kill -HUP $dead 2>&1 | grep -c 'invalid signal'; echo "c=${PIPESTATUS[0]}" - name: "kill takes options after a -SIG shorthand" known_failure: true # TODO(kill): a word after -SIG is taken for an operand ignore_stderr: true stdin: | # Each sends signal 0 to this shell, which only checks that it exists. kill -0 -n 0 $$; echo "a=$?" kill -TERM -s 0 $$; echo "b=$?" - name: "kill takes -- after a signal" known_failure: true # TODO(kill): `-9 --` takes `--` for a pid ignore_stderr: true stdin: | # An exited process's ID names no process or group, so nothing else is # signaled; only the reason kill gives for failing is compared. dead=$(sh -c 'echo $$') kill -9 -- $dead 2>&1 | grep -c 'invalid signal'; echo "a=${PIPESTATUS[0]}" kill -s HUP -- -$dead 2>&1 | grep -c 'invalid signal'; echo "b=${PIPESTATUS[0]}" - name: "kill -s takes a signal number" known_failure: true # TODO(kill): -s takes only signal names ignore_stderr: true stdin: | # The shell's termination status shows which signal it was sent. kill -s 15 $$ echo "survived: $?" - name: "kill -l with several signals prints each" known_failure: true # TODO(kill): `kill -l` with more than one signal fails as too many jobs stdin: | kill -l 15 9 - name: "kill -l maps an exit status above 128 to its signal" known_failure: true # TODO(kill): a status above 128 is an invalid signal specification stdin: | kill -l 129 - name: "kill -l lists the signals in columns" known_failure: true # TODO(kill): one signal a line, not bash's table stdin: | kill -l | head -n 1