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

Reply via email to