SCRIPT GOAL: the script is invoked as ./script.sh cmd1 cmd2 ... cmdn. It should executes in background all the commands passed as arguments from the command line and check when all of them have finished their execution. Furthermore if the SIGTERM signal is send to the script it should kill all the aforemoentioned processes (cmd1 ... cmdn) and then kill himself.

PROBLEM: All seem working except the autotermination and I can't figure out why. I tried to use kill $$ but at runtime I get segmentation fault. I was thinking that the problem was related to the fact that kill command is inside a function but on the other hand if I comment kill $$ and I leave kill ${PIDAR[*]} command, the latter work. Could somebody explain me what I am missing?


# signal handler                                                       
killemall () {                                                         
   echo $$                                                             
   kill ${PIDAR[*]}                                                  
   kill $$   # implicated line                                                           

PIDAR=() # pid array                                                   
STAR=() # process state array                                          

# execute processes in bg and save their pid                           
for i in "$@" ; do                                                     
    $i &                                                               

trap 'killemall' SIGTERM                                               

terminated=1  # flag to indicate when all processes are terminated     
while  sleep 1  && [ $terminated -eq 1 ]; do                           
   for (( i=0; i<${#PIDAR[*]}; i++ )); do                              
      STAR[$i]=$(ps hp ${PIDAR[$i]} | awk '{ print $3 }')              
      if [ -z ${STAR[$i]} ]; then                                      
      else terminated=1                                                
      echo "Process state ${PIDAR[$i]}:${STAR[$i]}" | tee -a logg  

echo "All processes are terminated"  


SOLUTION: as user18197 pointed out, the problem is calling kill $$. Indeed as the kill man page reports:

The default signal for kill is TERM

Then at each kill $$ invocation the script was calling the handler killemall which in turn was invoking again kill $$ and so on recursively. To avoid this behaviour we can untrap SIGTERM signal. As help trap reports:

If ARG is absent (and a single SIGNAL_SPEC is supplied) or `-', each specified signal is reset to its original value.

So the new function body is:

killemall () {     
   echo $$
   trap - SIGTERM
   kill ${PIDAR[@]}
   kill $$                

1 Answer 1


I couldn't reproduce the seg fault, but I am guessing that sending SIGTERM to yourself will reinvoke the killemall function, which will send SIGTERM, which will invoke the killemall ...

You actually do not need to do anything to terminate your script. The function killemall is called and when it is done the script will exit. You can add an exit 0 at the end of the function to make it more clear if you want.

  • A program that handles sigint and then dies is usually expected to kill itself by sigint, see for example: gnu.org/software/libc/manual/html_node/…
    – muru
    Apr 27, 2018 at 10:34
  • AFAIK, that part is handled by the shell, bash in this case.
    – user18197
    Apr 27, 2018 at 10:40
  • @user18197 not if you simply exit 0 in the trap handler.
    – muru
    Apr 27, 2018 at 10:44
  • 1
    @ikeDiM removing the trap handler using trap "" SIGINT and then kill the script.
    – muru
    Apr 27, 2018 at 10:59
  • 1
    @ikeDiM oh, sorry, I for some reason during the entire conversation I kept saying sigint instead of sigterm. What I mean it is something like: killemall () { trap '' SIGTERM; kill ${PIDAR[@]}; kill $$; }
    – muru
    Apr 27, 2018 at 11:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .