Re: Bugs in ERR and RETURN traps
On 2/19/15 2:54 PM, Paul Donohue wrote: > When an ERR trap is called, ${BASH_SOURCE[0]}, ${FUNCNAME[0]}, and $LINENO > normally indicate the file/function/line which called the command that > returned a non-zero status. This is good. > > However, if an ERR trap is called because a function returned a non-zero > status, then ${BASH_SOURCE[0]} and ${FUNCNAME[0]} still indicate the > file/function which called the function that returned a non-zero status, but > $LINENO indicates the line number of the last command in the function that > was called, and the line number of the call to the function is not available. > This doesn't really make sense. > > Example: > $ cat <<'END' >script1 > test_fun() { > return 1 > } > END > $ cat <<'END' >script2 > #!/bin/bash > # Some blank lines to adjust the line numbers relative to script1 > > source script1 > trap 'echo error at: ${BASH_SOURCE[0]} ${FUNCNAME[0]} $LINENO > ${BASH_LINENO[@]}' ERR > false # Trigger the ERR trap with a command on line 6 > test_fun # Trigger the ERR trap with a function on line 7 > END > $ chmod 755 script2 > $ ./script2 > error at: ./script2 main 6 0 > error at: ./script2 main 2 0 > $ > > This seems like a bug. I would expect one of two behaviors here: > 1) In the ERR trap on function return, $LINENO should point to the line which > called the function (just as ${BASH_SOURCE[0]} and ${FUNCNAME[0]} point to > the file/function which called the function that returned a non-zero status). > 2) In the ERR trap on function return, ${BASH_SOURCE[0]}, ${FUNCNAME[0]}, and > $LINENO should point to the last command executed within the function, and > ${BASH_SOURCE[1]} ${FUNCNAME[1]} ${BASH_LINENO[0]} should point to the caller > of the function. Thanks for the report. I agree that this is a bug, and that your first expected behavior is the correct one. Function execution should save and restore the value of LINENO that will be used in an ERR trap. This will be fixed in the next release. In the meantime, I have attached a patch you can experiment with. It may not apply cleanly to bash-4.3, and your line numbers will certainly vary. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/ *** ../bash-20150220/execute_cmd.c 2015-02-08 07:37:26.0 -0500 --- execute_cmd.c 2015-02-27 09:22:33.0 -0500 *** *** 4554,4557 --- 4554,4558 add_unwind_protect (pop_context, (char *)NULL); unwind_protect_int (line_number); + unwind_protect_int (line_number_for_err_trap); unwind_protect_int (return_catch_flag); unwind_protect_jmp_buf (return_catch);
Re: Bugs in ERR and RETURN traps
On 2/19/15 2:54 PM, Paul Donohue wrote: > The RETURN trap does not see the exit status of 'return', but rather the exit > status of the last command before 'return' was called. > > Example: > $ test_fun() > { > trap 'echo returned $?' RETURN > false # exit status is 1 > return 2 > } > $ test_fun > returned 1 > $ > > I intuitively expected the above to print 2 instead of 1. > > The bash man page states "Any command associated with the RETURN trap is > executed before execution resumes after the function or script." This is a > bit vague, but it seems to imply that the RETURN trap should run after the > `return` command is complete (since the `return` command is part of the > function and the RETURN trap runs "after the function"), which would imply > that $? should be set to the exit status of the return command in the RETURN > trap. So, the documentation seems to back up my intuition here... > > The problem I was actually trying to solve was to write a trap that ran only > if the function returned an error. An ERR trap would have been run if any > command within the function returned an error, which was not what I wanted. > So, I simply wrote a RETURN trap which checked $?, but $? did not give me the > return status of the function, so this didn't work. The RETURN trap is run in the function's context, so this approach will probably not do what you want. The idea is that the trap allows the function writer to do cleanup while still seeing variables in the function's scope, for example. It's not intended to reflect the state after the function's execution context is unwound. As I recall -- and this was a long time ago -- it came in as part of the bash debugger changes and these were the semantics from the start. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Bugs in ERR and RETURN traps
I posted bug reports at https://savannah.gnu.org/support/index.php?108738 and https://savannah.gnu.org/support/index.php?108749 but there seems to be very little activity (or none at all?) on the issue tracker, so I figured it might be a good idea to post to the mailing list too. I'm using bash 4.3.30(1) in Ubuntu, and have run across two odd behaviors in ERR and RETURN traps that I think are bugs. First: When an ERR trap is called, ${BASH_SOURCE[0]}, ${FUNCNAME[0]}, and $LINENO normally indicate the file/function/line which called the command that returned a non-zero status. This is good. However, if an ERR trap is called because a function returned a non-zero status, then ${BASH_SOURCE[0]} and ${FUNCNAME[0]} still indicate the file/function which called the function that returned a non-zero status, but $LINENO indicates the line number of the last command in the function that was called, and the line number of the call to the function is not available. This doesn't really make sense. Example: $ cat <<'END' >script1 test_fun() { return 1 } END $ cat <<'END' >script2 #!/bin/bash # Some blank lines to adjust the line numbers relative to script1 source script1 trap 'echo error at: ${BASH_SOURCE[0]} ${FUNCNAME[0]} $LINENO ${BASH_LINENO[@]}' ERR false # Trigger the ERR trap with a command on line 6 test_fun # Trigger the ERR trap with a function on line 7 END $ chmod 755 script2 $ ./script2 error at: ./script2 main 6 0 error at: ./script2 main 2 0 $ This seems like a bug. I would expect one of two behaviors here: 1) In the ERR trap on function return, $LINENO should point to the line which called the function (just as ${BASH_SOURCE[0]} and ${FUNCNAME[0]} point to the file/function which called the function that returned a non-zero status). 2) In the ERR trap on function return, ${BASH_SOURCE[0]}, ${FUNCNAME[0]}, and $LINENO should point to the last command executed within the function, and ${BASH_SOURCE[1]} ${FUNCNAME[1]} ${BASH_LINENO[0]} should point to the caller of the function. Second: The RETURN trap does not see the exit status of 'return', but rather the exit status of the last command before 'return' was called. Example: $ test_fun() { trap 'echo returned $?' RETURN false # exit status is 1 return 2 } $ test_fun returned 1 $ I intuitively expected the above to print 2 instead of 1. The bash man page states "Any command associated with the RETURN trap is executed before execution resumes after the function or script." This is a bit vague, but it seems to imply that the RETURN trap should run after the `return` command is complete (since the `return` command is part of the function and the RETURN trap runs "after the function"), which would imply that $? should be set to the exit status of the return command in the RETURN trap. So, the documentation seems to back up my intuition here... The problem I was actually trying to solve was to write a trap that ran only if the function returned an error. An ERR trap would have been run if any command within the function returned an error, which was not what I wanted. So, I simply wrote a RETURN trap which checked $?, but $? did not give me the return status of the function, so this didn't work. Thoughts on these? Is there a reason for the current behavior? Thanks!