Getting HUPed

l.mark.larsen lml at cbnews.att.com
Sat Mar 30 08:46:44 AEST 1991


In article <c8C901q64a9q00 at amdahl.uts.amdahl.com> krs at amdahl.uts.amdahl.com (Kris Stephens [Hail Eris!]) writes:
# In article <53902 at mirror.tmc.com> kiyun at mirror.UUCP (KiYun Roe) writes:
# >In article <d2wB01ev46cG00 at amdahl.uts.amdahl.com> krs at amdahl.uts.amdahl.com (Kris Stephens [Hail Eris!]) writes:
# >>The thing about the trapped command is that you don't need to issue
# >>an exit from within the command-series.  The sh (or ksh) will simply
# >>execute the command on its merry way out.

This is only true of the 0 (aka EXIT in ksh) "interrupt" - as KiYun pointed out
in his reply.

# Okay, it ain't clear to me from reading ksh.1.  If I....
# 
# 	trap 'echo "signalled"' 0 1 2 3 14 15
# 
# in a script (not in a function of the script), it *is* clear that 0
# will echo "signalled" and exit.  It's not clear to me what will happen
# on signals 1 2 3 14 15, though.
# 
# Should this work to (a) echo "signalled" and (b) exit, without recursion:
# 
# 	trap 'echo "signalled"; exit' 0 1 2 3 14 15
# 
# where by "without recursion" I mean successive firings on the trap?
# What would the exit code be if the trap is taken by execution of an
# 'exit 1' in the script?  Would it be 0 because the echo was a success?

No, it would be 0 because no argument is supplied to the exit.

# Should I, instead, do:
# 
# 	trap 'echo "signalled"' 0
# 	trap 'echo "signalled"; exit' 1 2 3 14 15
# 
# to avoid a possible recursion and protect the exit code?

This won't protect the exit code either.

# 
# Anyone *really* know?

Well, let me give it my best shot...

Think of traps as being like signal handlers in C under UNIX(TM).  If you
don't catch the signal, the default action is to terminate the program.  The
same is true of a shell script.  You can ignore signals in a program.  To
do the same in a shell script, you set the action to the null string:

trap "" 1 2 3 15	# ignore some interrupts

Finally, you can call some user-defined signal handler which can do pretty 
much anything you want.  In a shell script, the same is true.  (For the
remainder of my message, I'll be talking about ksh88e, which is what I use.
The principles are generally true with earlier versions of ksh or with the
Bourne shell.)

I have used traps quite a bit and had occasion to explore their behavior
rather thoroughly.  First of all, the book states that, if several events
("interrupts") occur at about the same time, they are handled in the following
order:

DEBUG
ERR
all true interrupts (in numerical order)
EXIT

The EXIT trap is called whenever you 'exit' explicitly or the script finishes
executing in some fashion.  Note that the shell also provides the -e flag
which is similar to, but separate from, the ERR trap.  This flag takes
precedence over the real interrupts and causes an exit to occur, which will
trigger any EXIT trap.  By the same token, DEBUG is similar to, but different
from, the -x flag.  With these ideas in mind, it is possible to do many
interesting things.

One other point about traps and true interrupts (e.g., SIGINT): two or more
in a row can cause the trap to be started multiple times (depending on how
close together the interrupts are and how long it takes to execute the trap
action), so I think it is best to reset the trap first thing to ignore future
interrupts:

trap 'trap "" 1 2 3 15; rm -f $TMPFILE; exit 1' 1 2 3 15

Finally, I usually prefer to set all my traps at once (whenever the action
is the same) but this can cause the EXIT trap to be called twice if a true
interrupt occurs.  It also would cause the script to always exit with a value
of 1.  To get around this, I take advantage of the fact that the trap action
is expanded at execution time, so I do something like this (note: you must use
single quotes (or something equivalent) to protect against the expansion of
$RET at the time the trap is set):

RET=1
trap 'trap "" 1 2 3 15; rm -f $TMPFILE; trap 0; exit $RET' 0 1 2 3 15

# the script does its thing and at the end or before an explicit call to
# exit, I put:

RET=0

So, what happens is that the call to 'rm -f $TMPFILE' is made just once,
regardless of whether the script terminates normally or not.  Also, the 
script exits with a value indicative of what caused it to terminate.  I've
noted one funny thing that I think is a bug (inherited from the Bourne shell?):
If SIGINT is sent with the traps as noted above, then $? is set to 129
rather than 1 (or even 130).  The ksh book states $? is the value of the last
command executed and that it is 128 plus the signal number when an interrupt
terminated the command.  In this case though, the last command executed by
the script is 'exit $RET', so I think the value of $? should be 1.  If the
script terminates due to some other signal (e.g., SIGHUP) the value of $? is
indeed 1.

Hope this helps...
L. Mark Larsen
lml at atlas.att.com



More information about the Comp.unix.shell mailing list