Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I really tried to find a better title for this question. I am open for suggestions.

I've written a bash script that traps EXIT and calls a function if that signal is received. It calls the same function when a file called stop exists. Here it is:

#!/bin/bash

TAIL_PID=0
CAT_PID=0

DEVICE=/dev/ttyACM0
WDIR=plasma
LOGFILE=$WDIR/$(date +%Y%m%d_%H%M%S.log)
CMDFILE=$WDIR/toDevice

function kill_tail
{
  if [ $TAIL_PID -ne 0 ]
  then
    kill $TAIL_PID
    TAIL_PID=0
    echo "killed tail"
  fi
}

function kill_cat
{
  if [ $CAT_PID -ne 0 ]
  then
    kill $CAT_PID
    CAT_PID=0
    echo "killed cat"
  fi
}

function on_die
{
  echo 't 0' >> $DEVICE
  kill_tail
  kill_cat
  echo "stopped logging"
}
trap on_die EXIT

# mount plasma oven directory if it is not already mounted
mountpoint -q $WDIR || sshfs user@server:plasma $WDIR    
# see if device is available/wait for device
while [ ! -c $DEVICE ]
do
  sleep 1
done
echo "Found controller"

# stop output, remove start and stop files
echo 't 0' >> $DEVICE
rm $WDIR/start $WDIR/stop

# outer loop
while [ 1 ]
do
  while [ ! -f $WDIR/start ]
  do
    sleep 1
  done
  rm $WDIR/start

  # stop output
  echo 't 0' >> $DEVICE

  # pass commands to device
  # but clear existing commands first
  > $CMDFILE
  tail -f $CMDFILE > $DEVICE &
  TAIL_PID=$!
  echo "tail PID = " $TAIL_PID

  # start logging
  cat $DEVICE >> $LOGFILE &
  CAT_PID=$!
  echo "cat PID = " $CAT_PID

  # start output
  echo 't 1000' >> $DEVICE
  echo "started logging to " $LOGFILE

  while [ ! -f $WDIR/stop ]
  do
    sleep 1
  done
  rm $WDIR/stop

  on_die

done # end of outer loop

When I run this script, after touch start, it gives me different output depending on whether I CTRL-C or touch stop. This is the output after CTRL-Cing:

killed tail
killed cat
stopped logging

This is the output after touch stop:

killed tail
killed cat
stopped logging
./mountPlasma: line 93: 21200 Terminated              tail -f $CMDFILE > $DEVICE
./mountPlasma: line 93: 21201 Terminated              cat $DEVICE >> $LOGFILE

Why? The same function is called, and I would expect the same output from both calls to on_die. The output indicates that the two extra messages are emitted on line 93, which is done # end of outer loop (the line number does not exactly match the code above, as I had to remove a few lines for this post).

As I am very unexperienced with bash, I don't know if there are any side-effects to this. Both tailand cat are killed as expected.

share|improve this question

1 Answer 1

up vote 1 down vote accepted

When you hit Ctrl-C, the running script gets SIGINT and propagates it to it's children, whereas on "regular" exit it would send the default SIGTERM (from the function registered with EXIT).

That said, there is a big difference between Ctrl-C and the stop condition. While the exit handler function gets called in both cases the actual events are completely different. In the case of SIGINT, the child processes are killed by that one (or at least are likely to be) and the shell interpreting the script doesn't have much chance to report this state change. In the other case it catches SIGCHLD from the terminated programs and displays the information message.

Now, you can get the message on SIGINT as well, provided you give the interpreting shell enough time to check (more precisely - since I don't think that shell would be leaving zombie processes around in this situation - to report the status of) its child processes. One way to do it would be using the wait builtin to actively wait for all or specified processes to change state. Blowing up the exit handler (e.g. with another sleep) might be an option too, but note that this actually is sort of a race condition between the interpreter terminating and checking on its children (hence the blocking wait is the safe way to do it).

share|improve this answer
    
When i touch stop, the script stops logging (kills cat and tail) and then waits for a start file again. It is not exiting, so your answer seems to describe a different situation –  Christoph Apr 17 '13 at 6:59
    
I missed the bit loop in your script... –  peterph Apr 17 '13 at 14:55
    
@Christoph does the updated answer make more sense to you? –  peterph Apr 19 '13 at 8:36
    
Yes it does! I just didn't have a chance to check the output when adding a wait in on_die because the "other end" of this script is causing problems. I will give you an update as soon as I can! –  Christoph Apr 19 '13 at 20:28
    
I added the wait and it's now giving me consistent output in the real application. Thank you! –  Christoph Apr 24 '13 at 11:38

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.