Bash: issuing trap twice

If I issue the trap builtin twice [for the same signal], what happens? Is the second command added to the first, or does it replace the first?

trap Foo SIGINT
...
trap Bar SIGINT
...

When SIGINT happens, does Bash just run Bar, or does it run Foo as well? Or something else…?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

The command is replaced.

The manpage states:

 trap [-lp] [[arg] sigspec ...]
        The  command  arg  is  to  be  read  and executed when the shell
        receives signal(s) sigspec.  If arg is absent (and  there  is  a
        single  sigspec)  or  -,  each  specified signal is reset to its
        original disposition (the value it  had  upon  entrance  to  the
        shell).   If arg is the null string the signal specified by each
        sigspec is ignored by the shell and by the commands it  invokes.
        If  arg  is  not present and -p has been supplied, then the trap
        commands associated with each  sigspec  are  displayed.   If  no
        arguments  are  supplied or if only -p is given, trap prints the
        list of commands associated with each  signal.   The  -l  option
        causes  the shell to print a list of signal names and their cor‐
        responding numbers.   Each  sigspec  is  either  a  signal  name
        defined  in  <signal.h>,  or  a signal number.  Signal names are
        case insensitive and the SIG prefix is optional.

It states the command arg is to be read and executed ... period. It would otherwise not be possible to reset the signal handling if the arg was always added to the list.

Method 2

From the manual:

trap [-lp] [arg] [sigspec …]

The commands in arg are to be read and executed when the shell receives signal sigspec.

The description doesn’t say anything about adding to an existing list of commands. It goes on to specify non-incremental effects when arg is empty or the string -. While the text might not explicitly say that the commands are not added to a list, it never mentions any such list, or any means to remove an item from said list. So interpreting this text in a way that would imply that successive trap commands add arg to a list is rather far-fetched.

You can make sure by checking another shell’s manual. If bash deviated from the usual behavior, the manual would clearly say so. The POSIX standard is unambiguous on the matter:

The action of trap shall override a previous action (either default action or one explicitly set).

Method 3

I still can’t find any documentation on the matter, but from my tests it appears that the second trap specification entirely replaces the first one. (I.e., Bar will be run, but Foo will not.)

Method 4

As already answered, the trap command replaces traps if already present.
In case you do actually want both present and new to be executed, I suppose you can hack around a bit:

function overtrap {
  trap="$1"
  sig=$(echo $2 | tr [a-z] [A-Z])
  cur="$(trap -p $sig | sed -nr "s/trap -- '(.*)' $sig$/1/p")"
  if test ${cur:+x}; then
    trap "{ $trap; }; $cur" $sig
  else
    trap "$trap" $sig
  fi
}

Invoking something like

overtrap 'echo hi' exit
overtrap 'echo ho' exit

would print

ho
hi

(But I have no idea how portable this is.)


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x