From ba76dfa458bbdf4540d7eec2ce0fe8ccae6e757f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 13 Sep 2018 16:46:31 +0200 Subject: [PATCH] Properly clean up subprocesses in tests Relying on the process group to figure out which processes to treat as children and grandchildren of the test run was not correct, as the testrunner didn't ensure it was creating a new process group. When running inside 'make check' the process group was actually that of make, not testrunner.sh. Since setpgid is not universally available, we iterate the process tree via ps, and kill the children recursively. --- testrunner.sh | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/testrunner.sh b/testrunner.sh index 6077eca..88afa6f 100755 --- a/testrunner.sh +++ b/testrunner.sh @@ -134,7 +134,7 @@ function testrunner::run_tests() { done if testrunner::function_declared teardown; then - teardown >>$test_output_file 2>&1 + teardown >>$test_output_file fi [[ $DEBUG -eq 1 ]] && testrunner::print_test_output "Teardown" @@ -210,14 +210,27 @@ function testrunner::print_test_output { fi } -function testrunner::signal_children() { - signal=${1:-KILL} - child_pids=($(ps -o pid= -g $$ | sort --reverse)) - # Remove first three (ps in subshell) and last (self) - child_pids=("${child_pids[@]:3:${#child_pids[@]}-4}") - for pid in "${child_pids[@]}"; do - echo "Sending $signal to PID $pid ($(ps -o command= $pid))" - kill -s $signal $pid >/dev/null 2>&1 +function testrunner::signal_children() +{ + local signal=${1:-TERM} + local pid=${2:-${BASHPID:-$$}} + + local child_pids=() + + IFS= + res=$(ps -o ppid,pid) + unset IFS + { + read # Skip header + while IFS=' ' read -r ppid cpid; do + test $ppid -eq $pid && child_pids+=($cpid) + done + }<<<"$res" + + local p + for p in "${child_pids[@]}"; do + testrunner::signal_children $signal $p + kill -$signal $p >/dev/null 2>&1 done } @@ -276,7 +289,7 @@ for testsuite in "${testsuites[@]}"; do printf "tests_total+=${tests_total}; tests_failed+=${tests_failed}" >&3 # Clean up if test didn't do it - testrunner::signal_children TERM >&2 + testrunner::signal_children TERM ) exec 4>&- if [[ $interrupted -eq 1 ]]; then