Configuration Information [Automatically generated, do not change]: Machine: aarch64 OS: darwin21.6.0 Compiler: clang Compilation CFLAGS: -DSSH_SOURCE_BASHRC uname output: Darwin rio 21.5.0 Darwin Kernel Version 21.5.0: Tue Apr 26 21:08:29 PDT 2022; root:xnu-8020.121.3~4/RELEASE_ARM64_T8101 arm64 Machine Type: aarch64-apple-darwin21.6.0
Bash Version: 5.2 Patch Level: 2 Release Status: release Description: We have found that [https://www.gnu.org/software/bash/manual/bash.html#Shell-Functions shell function] _declarations_: 0 do not emit trace output 0 do not call DEBUG trap 0 modify $? Unless we have missed the related documentation, we believe the current semantic to be at least unclear and would like to see either: 0 the DEBUG trap called _before_ any function declaration (preferred) 0 or function declarations preserving $? as they are not commands appearing in trace and DEBUG (has cons) Repeat-By: Thanks to @soliton on #iirc, we have a straightforward one-liner: +verbatim+ 1 ❯ bash -xc 'PS4="+(\$?) "; false; f() { :; }; echo end' 2 + PS4='+($?) ' 3 +(0) false 4 +(0) echo end 5 end -verbatim- f() declaration takes place in between line #3 and #4. The declaration itself evades the trace but still its exit status (0) replaces the one from false (1) (line #4). Here is another example showing that function declarations also escape DEBUG trap while having the same side effect on $?: +verbatim+ 1 ❯ cat main.bash 2 #!/bin/env bash 3 4 set -o functrace 5 trap 'echo "DEBUG> ($?) ${BASH_COMMAND}";' DEBUG 6 7 f() { 8 : f/start 9 false 10 # g()(( 0 )) 11 : f/survived 12 } 13 14 f && : top/success 15 16 ❯ bash ./main.bash 17 DEBUG> (0) f 18 DEBUG> (0) f 19 DEBUG> (0) : f/start 20 DEBUG> (0) false 21 DEBUG> (1) : f/survived 22 DEBUG> (0) : top/success 23 ❯ sed -i '' 's/# g/g/' main.bash 24 ❯ bash ./main.bash 25 DEBUG> (0) f 26 DEBUG> (0) f 27 DEBUG> (0) : f/start 28 DEBUG> (0) false 29 DEBUG> (0) : f/survived 30 DEBUG> (0) : top/success -verbatim- * When enabling functrace (line #4), the DEBUG trap becomes inherited by functions. * The DEBUG trap itself prints the _previous_ command exit status and the _next_ command. * During the first run (line #16), g() definition is commented out (line #10). * The exit status (1) of false (line #9) appears in the output (line #21). * The sed command (line #23) uncomment g() definition (line #10). * During the second run (line #24). The exit status (1) of false is no longer available: It has been replaced by 0 (line #29), thanks to the successful declaration of g() (line #10). * Just as before, the function declaration itself evades debugging (ie. It is never loaded in $BASH_COMMAND). We have traced this behaviour back to [http://git.savannah.gnu.org/cgit/bash.git/tree/execute_cmd.c#n6109 execute_intern_function()]. This function has no support for tracing nor trapping DEBUG. Should you consider to go on and discuss a solution, we will be happy to help. Best regards, erik