"trap" output from "if" statement redirected wrongly
Configuration Information [Automatically generated, do not change]: Machine: x86_64 OS: linux-gnu Compiler: gcc Compilation CFLAGS: -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wall uname output: Linux mars 5.10.0-12-amd64 #1 SMP Debian 5.10.103-1 (2022-03-07) x86_64 GNU/Linux Machine Type: x86_64-pc-linux-gnu Bash Version: 5.1 Patch Level: 16 Release Status: release Description: This script writes "foo" to bar rather than stdout as I'd expect. It's triggered by the "if" statement (which doesn't even cause running in a subshell, so it's not that). #!/bin/bash set -e trap 'echo foo' 0 #false > bar # "foo" written to stdout correctly if true; then false; else false; fi > bar # "foo" written to bar
Re: "trap" output from "if" statement redirected wrongly
On Wed, Apr 13, 2022 at 7:59 AM Frank Heckenbach wrote: > This script writes "foo" to bar rather than stdout as I'd expect. > > It's triggered by the "if" statement (which doesn't even cause > running in a subshell, so it's not that). > > #!/bin/bash > set -e > trap 'echo foo' 0 > #false > bar # "foo" written to stdout correctly > if true; then false; else false; fi > bar # "foo" written to bar I don't believe this is a bug, though Chet is welcome to chime in with an authoritative answer. The script exits after the else clause because false returns 1 and errexit is set. At this point in the program stdout has been redirect to the file bar, so when the trap echos to stdout its content goes to bar as well. I don't see anything in the docs about traps resetting their output file descriptors before they are ran. To work around this you need to save the original stdout file descriptor. Something like this: #!/bin/bash exec {STDOUT}>&1 exec {STDERR}>&2 set -e trap 'echo foo >&${STDOUT}' EXIT if true; then false; else false; fi >bar
Re: "trap" output from "if" statement redirected wrongly
> On Wed, Apr 13, 2022 at 7:59 AM Frank Heckenbach > wrote: > > This script writes "foo" to bar rather than stdout as I'd expect. > > > > It's triggered by the "if" statement (which doesn't even cause > > running in a subshell, so it's not that). > > > > #!/bin/bash > > set -e > > trap 'echo foo' 0 > > #false > bar # "foo" written to stdout correctly > > if true; then false; else false; fi > bar # "foo" written to bar > > I don't believe this is a bug, though Chet is welcome to chime in > with an authoritative answer. The script exits after the else clause > because false returns 1 and errexit is set. At this point in the program > stdout has been redirect to the file bar, so when the trap echos to > stdout its content goes to bar as well. I don't see anything in the > docs about traps resetting their output file descriptors before they > are ran. I don't see anything to the contrary either. Syntactically, the redirection applies to the main statement, not the trap. When and how redirections are set up and reset is an implementation detail. Moreover, I don't see anything that would make a difference between the "if" statement and the plain one, so if the behaviour you describe is correct, the bug is that the non-"if" statement actually writes to stdout. :P > To work around this you need to save the original stdout file > descriptor. I know how to work around. But that makes me wonder. What is actually required to use a trap-statement safely (meaning, in a non-surprising way)? I know (for an EXIT trap) to save "$?" and "rethrow" it, now it seems one needs to save all FDs it might use (STDOUT, STDERR, maybe STDIN or other FDs one might redirect somewhere). What else is required? Is this documented anywhere?
Bash-5.2-beta available
The first beta release of bash-5.2 is now available with the URLs ftp://ftp.cwru.edu/pub/bash/bash-5.2-beta.tar.gz https://ftp.gnu.org/pub/gnu/bash/bash-5.2-beta.tar.gz and from the bash-5.2-testing branch in the bash git repository (http://git.savannah.gnu.org/cgit/bash.git/log/?h=bash-5.2-testing). You can use git clone --branch bash-5.2-testing git://git.savannah.gnu.org/bash.git to clone the testing branch. The CWRU FTP site works best if your client supports Extended Passive (EPSV) mode. This tar file includes the formatted documentation (you should be able to generate updated versions yourself). This release fixes several outstanding bugs in bash-5.1 and introduces a number of new features. There are significant new features of note: * The parser now calls itself recursively to parse command substitutions, and reconstitutes the text from the parsed command. This allows better syntax checking and catches errors much earlier; * Bash-5.2 improves associative array subscript parsing with the goal of eliminating double evaluation for shell constructs such as arithmetic expansion and conditional commands, the `unset' builtin, and arguments to other builtin commands as long as assoc_expand_once is set; * Associative arrays now allow assignment to and unsetting `@' and `*' keys, and the `unset' builtin treats `@' and `*' keys differently to allow this; * There is an alternate array implementation, selectable at configuration time, that optimizes access speed over memory use (but can use considerably more memory for large sparse arrays); * There is a configuration option to compile $"..." string translation out of the shell, and a runtime shell option to inhibit any additional expansion of translated strings; * The new `varredir_close' shell option causes bash to automatically close file descriptors opened with {var} 128 in the current encoding. hh. Fixed a problem that could cause the shell to attempt to free unallocated memory if an expansion error occurred. ii. Fixed a bug in the bash malloc implementation of malloc_usable_size. Bash did not use it, but it could cause problems with library functions that did. jj. If the `exec' builtin fails, and the shell does not exit, it restores trapped signals to their trapped state. kk. Fixed a bug that could cause variable assignment arguments to `declare' to expand variables using attributes that the call to declare was turning off. ll. Fixed a bug with LINENO and arithmetic for commands. mm. Fixed a posix-mode bug that caused tildes not to be expanded after an unquoted colon on the right side of an assignment statement. nn. Fixed a problem with `caller' and line numbers when executing an ERR trap. oo. Fixed a problem that could make the value returned by ${a:=b} not be the final value assigned to a (e.g., if `a' has an attribute that modifies the value on assignment). pp. Fixed a problem with saving multi-line here-documents to the history list where the here-document delimiter does not appear on the first line. qq. Fixed a bug with using += to assign to dynamic variables like RANDOM. rr. Fixed a bug that caused `set -n' to modify $? if set after execution had started. ss. Builtins like printf/read/wait now behave more consistently when assigning arbitrary keys to associative arrays (like `]'. when appropriately quoted). tt. Fixed a problem with here-document collection printing the wrong prompt when parsing a compound list in an interactive shell. uu. Fixed a problem with quoting shell expansion characters (like `$') when they appear in a tab-completed word along with characters that do need quoting (e.g.. $HOME/VirtualBox VMs). 2. Changes to Readline a. Fixed a problem with cleaning up active marks when using callback mode. b. Fixed a problem with arithmetic comparison operators checking the version. c. Fixed a problem that could cause readline not to build on systems without POSIX signal functions. d. Fixed a bug that could cause readline to crash if the application removed the callback line handler before readline read all typeahead. e. Added additional checks for read errors in the middle of readline commands. f. Fixed a redisplay problem that occurred when switching from the digit- argument prompt `(arg: N)' back to the regular prompt and the regular prompt contained invisible characters. g. Fixed a problem with restoring the prompt when aborting an incremental search. h. Fix a problem with characters > 128 not being displayed correctly in certain single-byte encodings. i. Fixed a problem with unix-filename-rubout that caused it to delete too much when applied to a pathname consisting only of one or more slashes. j. Fixed a display problem that caused the prompt to be wrapped incorrectly if the screen changed dimensions during a call to readline() and the prompt became longer than the screen width. k. Fixed a problem