I have a question on the POSIX behavior of `return' shell builtin without arguments when used in a shell `trap' action. I initially came to this question in investigating an infinite-loop issue reported by Silvio Knizek at
https://github.com/akinomyoga/ble.sh/issues/48 . Then, I discussed the issue in bug-bash mailing list where I was introduced to the austin-group list by Chet. This is the thread: https://lists.gnu.org/archive/html/bug-bash/2020-04/threads.html#00089 The corresponding section in POSIX is as follows: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_24_14 > [XCU 2.14 Special Built-In Utilities - return - EXIT STATUS] > > 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 n is not an unsigned decimal > integer, or is greater than 255, the results are unspecified. When > return is executed in a trap action, the last command is considered > to be the command that executed immediately preceding the trap > action. What does ``When return is executed in a trap action'' exactly mean? There can be two interpretations: (A) `return's specified in the argument string of `trap' builtin (or, more specifically, `return's which terminate the trap action) are affected, or (B) all the `return's in an entire runtime function-call tree in trap processing are affected. Literally, it reads like the interpretation (B), but it seems unreasonable. - If this exception of `return' in trap actions aims to provide a way to recover the value of $? before the trap handler is invoked, the behavior (A) is enough, and there is no need to affect every `return's in the function-call tree as in (B). - If the behavior of no-argument `return's can be changed in functions as in (B), one cannot reliably use no-argument `return's in the functions that can be possibly be used in trap handlers. Actually this caused the infinite loop I mentioned above in Bash 5.0 which implements the interpretation (B). With interpretation (B), it seems hard to work around it properly. - If the literal interpretation (B) is correct, what is the use case of this behavior, or what is the rationale for this behavior? In fact, the implementation in shells varies. I have tested using the following script: # 0015-test4.sh setexit() { return "$1"; } invoke() { kill -USR1 $$; return 222; } trap 'setexit 111; return' USR1 invoke case $? in (0) echo 'In trap argument: last command preceding the trap action' ;; (111) echo 'In trap argument: last command in the trap action' ;; (222) echo 'In trap argument: (failed to exit the function)' ;; (*) echo 'In trap argument: (unexpected)' ;; esac stat=99 handler() { setexit 111; return; } trap 'handler; stat=$?; return' USR1 invoke case $stat in (0) echo 'In function call: last command preceding the trap action' ;; (111) echo 'In function call: last command in the trap action' ;; (*) echo 'In function call: (unexpected)' ;; esac `zsh-5.7.1', `dash-0.5.10.2' and `busybox-1.28.3' implements the interpretation (A) which produces the following result: In trap argument: last command preceding the trap action In function call: last command in the trap action `bash-4.4', `ksh-2020.0.0' and `mksh R57' implements the interpretation (B) which produces the following result: In trap argument: last command preceding the trap action In function call: last command preceding the trap action `bash-4.3' and `posh-0.13.2' does not implement the special treatment in a trap action. In trap argument: last command in the trap action In function call: last command in the trap action `yash-2.49' seems to try to implement the interpretation (B), but it behaves differently from other shells. In trap argument: (failed to exit the function) In function call: last command preceding the trap action It seems `yash' fails to follow the following description. https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_28_03 > XCU 2.14 Special Built-In Utilities - trap - DESCRIPTION > > Each time trap is invoked, the action argument shall be processed > in a manner equivalent to: > > eval action Thank you. -- Koichi Murase