5

I'm dabbling in traps in Bash again. I've just noticed the RETURN trap doesn't fire up for functions.

$ trap 'echo ok' RETURN
$ f () { echo ko; }
$ f
ko
$ . x
ok
$ cat x
$ 

As you can see it goes off as expected for sourcing the empty file x.

Bash's man has it so:

If a sigspec is RETURN, the command arg is executed each time a shell function or a script executed with the . or source builtins finishes executing.

What am I missing then?

I have GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu).

  • The trap only fires if function is executed in . or source context. In your example, it works as expected. Calling f alone not trigger the trap. – cuonglm Jan 23 '18 at 7:43
  • @cuonglm So if x contains f then the trap should fire up twice? – Tomasz Jan 23 '18 at 7:48
  • No, only once. The trap fire up after each . or source – cuonglm Jan 23 '18 at 7:56
  • @cuonglm What makes you think so? Is the documentation not up to date? – Tomasz Jan 23 '18 at 8:00
  • That's what I understand when reading the doc. Each time . or source finish executing, if trap RETURN is installed, it will be executed. – cuonglm Jan 23 '18 at 8:37
4

As I understand this, there's an exception to the doc snippet in my question. The snippet was:

If a sigspec is RETURN, the command arg is executed each time a shell function or a script executed with the . or source builtins finishes executing.

The exception is described here:

All other aspects of the shell execution environment are identical between a function and its caller with these exceptions: the DEBUG and RETURN traps (see the description of the trap builtin under SHELL BUILTIN COMMANDS below) are not inherited unless the function has been given the trace attribute (see the description of the declare builtin below) or the -o functrace shell option has been enabled with the set builtin (in which case all functions inherit the DEBUG and RETURN traps), and the ERR trap is not inherited unless the -o errtrace shell option has been enabled.

As for functrace, it can be turned on with the typeset's -t:

-t Give each name the trace attribute. Traced functions inherit the DEBUG and RETURN traps from the calling shell. The trace attribute has no special meaning for variables.

Also set -o functrace does the trick.

Here's an illustration.

$ trap 'echo ko' RETURN
$ f () { echo ok; }
$ cat y
f
$ . y
ok
ko
$ set -o functrace
$ . y
ok
ko
ko

As for declare, it's the -t option again:

-t Give each name the trace attribute. Traced functions inherit the DEBUG and RETURN traps from the calling shell. The trace attribute has no special meaning for variables.

Also extdebug enables function tracing, as in ikkachu's answer.

1

On Bash 4.4., it only seems to work for functions if extdebug is enabled, though I can't see that mentioned in the documentation.

$ cat ret.sh 
trap "echo ret" RETURN
foo() { echo "$1"; }
foo "without extdebug"
shopt -s extdebug
foo "with extdebug"

$ bash ret.sh
without extdebug
with extdebug
ret

$ bash --version |head -1
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)

In Bash 4.3, it doesn't seem to work for functions at all.

  • extdebug's description has it. 5. Function tracing is enabled: command substitution, shell functions, and subshells invoked with ( command ) inherit the DEBUG and RETURN traps. – Tomasz Jan 23 '18 at 9:55
  • And it's not only with extdebug. See my answer unix.stackexchange.com/a/419045/181255 – Tomasz Jan 23 '18 at 9:56
  • @tomasz, bah, I looked at extdebug, but didn't see it. I'm a bit amused the requirements aren't mentioned under trap. – ilkkachu Jan 23 '18 at 10:13
  • @ikkachu I often have an impression Bash's man is a can of spam. – Tomasz Jan 23 '18 at 10:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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