According to POSIX: | The value of the special parameter '?' shall be set to n, an | unsigned decimal integer, or to the exit status of the last command | executed if n is not specified. If the value of n is greater than | 255, the results are undefined. When return is executed in a trap | action, the last command is considered to be the command that | executed immediately preceding the trap action.
Source (EXIT STATUS section): http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#return So, what I understand from this: (1) When return is called without a numeric argument, the code returned is that of the `last command'. (2) The `last command' is defined as: ``[...] the command that executed immediately preceding the trap action''. Taking the SYNOPSIS for the trap builtin: | trap n [condition...] | trap [action condition...] and from DESCRIPTION: | Each time trap is invoked, the action argument shall be processed in | a manner equivalent to: | | eval action Source: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#trap So as I read it, `action' refers to the whole string. Now, this means, taking the following pseudo-code: | trap '(exit BEFORE-RETURN); return' SIGNAL | | fn() { | (exit BEFORE-ACTION); -block here waiting for signal- | } If that script receives SIGNAL, it should return the BEFORE-ACTION exit code, and not the BEFORE-RETURN exit code. Testing this is a bit tricky, because there's no simple way of blocking to wait for a signal in a way that it doesn't affect our testing, so the bes I could come up with is this: ### begin test script code='trap "(exit 2); return" USR1 f() { { echo; kill -USR1 $$; } | exit 3 return 5 } (exit 7); f ' shells=( bash 'bash --posix' ksh mksh dash 'busybox sh' zsh jsh ) for attempt in {1..1000}; do for shell in "${shells[@]}"; do printf '%s: %s\n' "$shell" "$($shell -c "$code"; echo $?)" done done | sort | uniq -c ### end test script And sample output from this script: 969 bash: 2 31 bash: 5 979 bash --posix: 2 21 bash --posix: 5 1000 busybox sh: 5 971 dash: 3 29 dash: 5 118 jsh: 3 882 jsh: 5 1 ksh: 0 999 ksh: 3 970 mksh: 3 30 mksh: 5 6 zsh: 2 994 zsh: 3 As you can see from the results, both bash and zsh, when signaled at the right time, return `BEFORE-RETURN', which in the script was set as 2. zsh sometimes returns `BEFORE-ACTION' though. dash, jsh, ksh, and mksh follow POSIX, in the sense that they usually return 3, (BEFORE-ACTION). And busybox is just playing alone in there, it appears as it cannot handle that trap correctly. The versions tested are: bash --version|head -n1: GNU bash, version 4.3.0(2)-release (x86_64-unknown-linux-gnu) zsh --version|head -n1: zsh 4.3.17 (x86_64-unknown-linux-gnu) ksh --version|head -n1: version sh (AT&T Research) 93u+ 2012-02-29 mksh -c 'echo "$KSH_VERSION"': @(#)MIRBSD KSH R40 2012/07/20 Debian-7 apt-cache policy dash|grep Installed: Installed: 0.5.7-3 apt-cache policy busybox|grep Installed: Installed: 1:1.20.0-7 head -n3 ~/local/src/heirloom-sh/CHANGES: Release ... * A bug in the supplied realloc() replacement could result in heap corruption. (No resulting failures have been observed with sh so far.) -- Eduardo Alan Bustamante López