Things seem a little more subtle:

In order do make some light on this, ther's my version:

    #!/bin/bash
    
    jobs=()
    
    cleanup() {
        echo "PID: $$ CMD: $BASH_COMMAND"
        kill -- "${jobs[@]}"
        wait
    }
    
    trap cleanup EXIT
    
    true & jobs+=($!)
    true & jobs+=($!)
    true & jobs+=($!)
    true & jobs+=($!)
    true & jobs+=($!)
    
    # trap cleanup EXIT
    
    declare -p jobs

Run on Debian Trixie (bash 5.2.15(1)-release), when `trap` is defined
before `true` commands, I often (but not always) see:

    declare -a jobs=([0]="253085" [1]="253086" [2]="253087" [3]="253088" 
[4]="253089")
    PID: 253084 CMD: declare -p jobs
    trapChilds.sh: line 7: kill: (253085) - No such process
    trapChilds.sh: line 7: kill: (253086) - No such process
    trapChilds.sh: line 7: kill: (253087) - No such process
    PID: 253084 CMD: true
    trapChilds.sh: line 7: kill: (253085) - No such process
    trapChilds.sh: line 7: kill: (253086) - No such process
    trapChilds.sh: line 7: kill: (253087) - No such process

Where `cleanup` was run two times! Seem to be trigger by one of `true`
command's EXIT signal.

( $BASH_COMMAND should contain `declare -p` !)

When run on 5.3.9(1)-release, I see sometime:

    declare -a jobs=([0]="254729" [1]="254730" [2]="254731" [3]="254732" 
[4]="254733")
    PID: 254727 CMD: declare -p jobs
    trapChilds.sh: line 7: kill: (254729) - No such process
    trapChilds.sh: line 7: kill: (254730) - No such process
    trapChilds.sh: line 7: kill: (254731) - No such process
    trapChilds.sh: line 7: kill: (254732) - No such process
    trapChilds.sh: line 7: kill: (254733) - No such process

But some other time: 

    declare -a jobs=([0]="254707" [1]="254708" [2]="254709" [3]="254710" 
[4]="254711")
    PID: 254705 CMD: declare -p jobs
    trapChilds.sh: line 7: kill: (254707) - No such process
    trapChilds.sh: line 7: kill: (254710) - No such process
    PID: 254705 CMD: true
    PID: 254705 CMD: true
    trapChilds.sh: line 7: kill: (254707) - No such process
    trapChilds.sh: line 7: kill: (254707) - No such process
    trapChilds.sh: line 7: kill: (254710) - No such process
    trapChilds.sh: line 8: wait: pid 254708 is not a child of this shell
    trapChilds.sh: line 8: wait: pid 254708 is not a child of this shell
    trapChilds.sh: line 8: wait: pid 254708 is not a child of^C

I had to hit Ctrl+C!

Note: If the trap is defined AFTER last `true` was ran, everything work fine.

Le Mon, Jan 05, 2026 at 11:50:24AM -0500, Chet Ramey a écrit :
> On 1/2/26 2:23 PM, Aleksey Covacevice wrote:
> 
> > Bash Version: 5.3
> > Patch Level: 8
> > Release Status: release
> > 
> > Description:
> >      `wait` triggers an infinite "pid is not a child of this shell" loop 
> > when
> >      used in an EXIT trap.
> > 
> > Repeat-By:
> >      Run the following:
> > ....
> >      Ocasionally bash loops at `wait` claiming some "pid is not a child of
> >      this shell". (It doesn't happen if `kill` is not used.)
> 
> Consider this sequence of events. The parent shell forks the last
> asynchronous process and adds it to the jobs array (setting the
> value of $! and adding it to the list of background jobs the shell
> maintains). It then exits and runs its exit trap before the child process
> runs and resets its EXIT trap handler. The parent shell, as part of its
> EXIT trap, kills the last asynchronous child, which still has an active
> EXIT trap, with a SIGTERM. Since the shell is not interactive, SIGTERM is
> a fatal signal. That asynchronous child shell exits, running its EXIT trap.
> 
> The child process, which has an active EXIT trap, has inherited the jobs
> array, the list of background processes, and the value of $! from its
> parent. When it runs its EXIT trap, it will try to wait for all of the
> background jobs it inherited, none of which are its children. You should
> get at least one error message when this happens.
> 
> The loop happens because it keeps trying to wait for these processes that
> are not its children. I'll have to figure out why that's happening --
> probably because it's trying to wait for "all background pids" and not
> doing the right error checks.

-- 
 Félix Hauri  -  <[email protected]>  -  http://www.f-hauri.ch

Reply via email to