Issue
I have a BASH to run 3 functions in parallel in my BASH.
functionA () {
......
my command || { echo "ERROR!!" >> $LOG_FILE ; exit 1 ;}
}
functionB () {
......
my command || { echo "ERROR!!" >> $LOG_FILE ; exit 1 ;}
}
functionC () {
......
my command || { echo "ERROR!!" >> $LOG_FILE ; exit 1 ;}
}
functionA &
functionB &
functionC &
wait
I have some commands in all functions for Error handling like this:
my command || { echo "ERROR!!" >> $LOG_FILE ; exit 1 ;}
I noticed even though I have exit 1 for Error handling in all functions but the other functions still keep going. How do I stop bash and return exit code 1 if any of the functions fail?
I am very new to BASH, any help is appreciated!
Solution
update: Testing my original code with a large number of sub-processes terminating at the same time showed that some kind of exclusive locking mechanism is needed; I implemented a simple one (that is atomic) using the widely available mktemp -d
and a symlink.
#!/bin/bash
lockdir=$(mktemp -d) || exit "$?"
trap 'exit 1' ABRT
trap 'mv "$lockdir" "$lockdir~" && rm -rf "$lockdir~"; kill 0' EXIT
diex() { ln -s _ "$lockdir/.lock" 2> /dev/null && kill -ABRT "$$"; }
{ sleep 1; echo "ERROR!!"; diex; } &
{ sleep 2; echo "HELLO!!"; } &
wait
note: Here I assume that "$lockdir~"
doesn't exist. If it isn't good enough for you then you can create an other directory with mktemp -d
and use it as a trash-bin before deleting it.
Explanations:
The idea is to make the sub-processes notify the main script with kill -ABRT "$$"
when they fail.
I chose the SIGABRT
signal because it is appropriate for the purpose of aborting, but it has the effect of disabling the automatic generation of the core-dump normally done when receiving SIGABRT
. If you're running an OS that supports SIGUSR1
and SIGUSR2
then you can use it instead.
- At the start of the script, you define some signal listeners with
trap
and associate a command to be run when catching a signal of the specified types:
The listener for the
EXIT
signal (triggered for example by anexit
command in the main script context) will terminate the script and all its sub-processes withkill 0
.The listener for
SIGABRT
(sent by the sub-processes) will not only generate anEXIT
signal but also set the exit status to1
.
- The locking mechanism is to prevent more than one
SIGABRT
signal to be sent.
Answered By - Fravadona Answer Checked By - Timothy Miller (WPSolving Admin)