3
\$\begingroup\$

This is my solution using job control.

  1. Whenever a job dies, it kills the parent script
  2. When the parent script dies, it kill the whole process group, including all jobs

I would hope that there's something simpler out there.

#!/usr/bin/env bash

# Mocks

function process () {
    while true ; do
    echo "Process $1 is working..."
    sleep 10
    done
}

# Actual implementation

trap terminate_entire_process_group EXIT
function terminate_entire_process_group () {
    trap - EXIT
    kill -15 -$$
}

function terminate_parent_process () {
    trap - EXIT
    kill $$ 2> /dev/null
}

(
    trap terminate_parent_process EXIT
    process 1
) &

(
    trap terminate_parent_process EXIT
    process 2
) &

wait
\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

This is clear and readable code - nice work.

Current style is to use portable syntax to define functions (i.e. omitting the function keyword). I recommend you stick to that.

If you're happy for all background tasks to terminate the process group (rather than having some which should and some which shouldn't), then we can just wait for the first background task to exit, using wait -n. It might also be a good idea to pass -f here, in case any child is stopped and restarted.

It might be necessary to send SIGKILL to processes that fail to exit on signal 15 (but prefer to use the symbolic name here - -TERM - or just omit it, since that's the default signal).

We can't be sure that the shell has its own process group (when I run it from Make, then Make itself is the process group leader, and kill -$$ is an error). Similarly, if the shell has job control enabled, then each background job will be leader of its own process group.

It might be better to list the jobs and target the signal at the children exactly:

kill_children() {
    #echo "Killing children" $(jobs -l | cut -d' ' -f2) >&2
    # assuming GNU xargs
    jobs -l | cut -d' ' -f2 | xargs --no-run-if-empty kill
}
trap kill_children EXIT
    
process 1 &
process 2 &
process 3 &

wait -fn
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.