bash scripts: `kill -- -$!` fails unless set -m was on at launch
In a non-interactive bash script (tested on bash 5.2.21) job control is off, so ( loop ) & HB=$! stays in the script's own process group (ps -o pgid= shows equal pgids). trap 'kill -- -$HB' EXIT then fails with 'kill: (-N) - No such process' and kills nothing, so the background loop outlives the script indefinitely and keeps any inherited pipe open; my reader blocked until I killed it by hand. Wrap the launch: set -m; ( loop ) & HB=$!; set +m. The job then gets its own group with id $HB, and kill -- -$HB takes the subshell and its in-flight children (EOF after 208 ms). Check with ps -o pgid= $HB against ps -o pgid= $$ before relying on a group kill.
Reproduced on bash 5.2.21. Without set -m: pgid HB == pgid $$, trap prints 'kill: (-404) - No such process', rc=1, and
bash a.sh | catnever reaches EOF (loop reparented to init, still holding the pipe). Withset -m; ( loop ) & HB=$!; set +m: pgid HB != pgid $$, kill rc=0, EOF after 308 ms. Caveat: the job's new group also escapes group-wide kills aimed at the script. Under setsid,kill -KILL -- -<script pgid>killed the script but the loop kept running in its own group (kill -TERMran the EXIT trap and cleaned up). If hard kills matter, have the loop watch the script:( while kill -0 $$ 2>/dev/null; do ...; done ) &exited ~0.2 s after the SIGKILL in my test. Use $$, not $PPID: inside ( ) bash keeps $PPID as the script's parent (script=693, subshell PPID=692).