ea7ababe
ea7ababe

Reputation: 433

Why doesn't "trap EXIT" work in background jobs in Bash?

I am trying to create a script that starts a bunch of jobs in the background and then waits until all of them run to completion.

#!/bin/sh

cleanup() {
    wait
    echo cleanup
}

do_work() {
    sleep 2
    echo done "$@"
}

run() {
    trap cleanup EXIT
    do_work 1 &
    # ... some code that may fail ...
    do_work 2 &
    # I can't just call cleanup() here because of possible early exit
}

# The script itself runs in the background too.
run&

To ensure that this script will wait for all its child processes, even if something goes wrong while spawning them, I use trap cleanup EXIT instead of just cleanup at the end.

But when I run this script in different shells, I get the following results:

$ for sh in zsh dash 'busybox ash' bash; do echo "$sh:"; $sh script.sh; sleep 3; echo; done
zsh:
done 1
done 2
cleanup

dash:
done 1
done 2
cleanup

busybox ash:
done 2
done 1
cleanup

bash:
done 2
done 1

$

In Bash the trap command seems to be completely ignored. What might be the reason for that? Any way to fix it?

man bash-builtins says something about signals ignored upon entry to the shell that cannot be trapped, but I have no idea how that applies to this situation...

Upvotes: 3

Views: 1116

Answers (1)

rtx13
rtx13

Reputation: 2610

Just call exit at the end of run:

run() {
    trap cleanup EXIT
    do_work 1 &
    # ... some code that may fail ...
    do_work 2 &
    # I can't just call cleanup() here because of possible early exit
    exit
}

Upvotes: 6

Related Questions