0

I have a shell script, which is executing a program fuseIO which is basically a C program.

Ths idea is, this executable fuseIO may throw a SIGABRT by an abort( ) call inside it, in which case, the while loop should exit.

How to accomplish that?

i=0
while [ $i != 10 ]
do
   echo "************ Iteration: $i *********\n" 2>&1 |tee -a log.txt
   ./fuseIO 2>&1 | tee -a log.txt // This may throw SIGABRT
   i=`expr $i + 1`
   sleep 1
done
RajSanpui
  • 11,556
  • 32
  • 79
  • 146
  • You'll need the `bash` PIPESTATUS environment variable, and you'll need to look for the correct exit status (probably 134, based on 128 plus signal number 6). – Jonathan Leffler Aug 21 '13 at 18:26
  • @JonathanLeffler: What is this 128? – RajSanpui Aug 21 '13 at 18:28
  • @JonathanLeffler: I just now read about this env variable. `The members of the $PIPESTATUS array hold the exit status of each respective command executed in a pipe` But what, if there was no `pipe` and a `tee` in my script, and it was just executed as `./fuseIO`? – RajSanpui Aug 21 '13 at 18:31
  • @JonathanLeffler: I tried this, but no use :-( `if [ $PIPESTATUS[0] == 134 ] then echo "Caught a signal" exit 1; fi` – RajSanpui Aug 21 '13 at 18:41
  • It's modestly complex — I'm not sure I can spend the time explaining it right now (and I was hoping someone else would step up and fill in the details for you/me). In part, see [Exit status codes greater than — possible?](http://stackoverflow.com/questions/179565/) The WIFSIGALED stuff tells you that a process was signalled, but there's a problem for the shell encoding that, and it does it (or seems to do it), by encoding a signalled exit status as 128 + signal number (129 for HUP, 130 for INT, etc). I'm not sure if `$PIPESTATUS` has to be enabled — check that, too. – Jonathan Leffler Aug 21 '13 at 18:48
  • I think you need to use `${PIPESTATUS[0]}` to get the number; you probably compared `0[0]` (or `134[0]`) with `134` and they weren't equal. – Jonathan Leffler Aug 21 '13 at 19:23
  • @JonathanLeffler: Just now tested and works great, yeah that's the problem it seems using the `pipe` and the `tee`. Request if you can please add it to your answer for everyone's benefit. – RajSanpui Aug 21 '13 at 19:35

1 Answers1

2

In part, see Exit status codes greater than — possible? The WIFSIGNALED stuff tells you that a process was signalled, but there's a problem for the shell encoding that, and it does it by encoding a signalled exit status as 128 + signal number (129 for HUP, 130 for INT, etc). To demonstrate shell and signal exit statuses:

$ cat killme.sh
#!/bin/bash
kill ${1:-"-INT"} $$
$ ./killme.sh -HUP; echo $?
Hangup: 1
129
$ ./killme.sh -TERM; echo $?
Terminated: 15
143
$ ./killme.sh -QUIT; echo $?
0
$ ./killme.sh -PIPE; echo $?
141
$ ulimit -a
core file size          (blocks, -c) 0
...
$

This more or less justifies my '128+signum' claim (the -QUIT behaviour is unexpected, but explainable after a fashion — it normally dumps core, but didn't because ulimit has them disabled).

In bash, you can get 'a list of exit status values from the processes in the most-recently-executed foreground pipeline (which may contain only a single command)' via the array $PIPESTATUS. For example:

$ ./killme.sh | exit 31

$ echo ${PIPESTATUS[*]}
130 31
$

This corresponds to the 130 exit status for SIGINT (2) plus the explicit exit status 31. Note the notation: ${PIPESTATUS[0]} with the braces around the indexing. Double quotes and things work like $* vs $@ vs "$*" vs "$@" for getting all the values in the array.

Applied to your two-part pipeline, you should be able to test:

if [[ ${PIPESTATUS[0]} == 134 ]]
then : FuseIO crash with SIGABRT
fi

Without the | tee, you can simply test $?:

if [[ $? > 128 && $? < 160 ]]
then : died a signalled death (probably)
else : died an ordinary death
fi

The 160 here is also an informed guess; it should be 128+SIGRTMAX. Note that if a process does exit 135, it will be treated as if it was signalled (even if it does not).

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278