On 7/23/19 12:12 PM, Sam Liddicott wrote: > Given what you have explained as intentional, it the difference between 1 > and 2, but it is best understood as a 4-way difference, outlined here: > > 1. {var} internal: fd remains open in parent > 2. {var} external: fd closed in parent > 3. numeric internal: fd closed in parent > 4. numeric external: fd closed in parent > > 1. {var} internal: fd remains open in parent > bash -c 'echo 1 {_}>&2 2>&1 1>&${_} {_}<&- ; > echo done ; lsof -p $$ | grep CHR' > > 2. {var} external: fd closed in parent > bash -c '/bin/echo 1 {_}>&2 2>&1 1>&${_} {_}<&- ; > echo done ; lsof -p $$ | grep CHR' > > 3. numeric internal: fd closed in parent > bash -c 'echo 1 10>&2 2>&1 1>&10 10<&- ; > echo done ; lsof -p $$ | grep CHR' > > 4. numeric external: fd closed in parent > bash -c '/bin/echo 1 10>&2 2>&1 1>&10 10<&- ; > echo done ; lsof -p $$ | grep CHR' > > You've indicated that {var} syntax leaves me an fd to do with what I wish.
Yes. The question is whether the {_}<&- should close the file descriptor `permanently' or whether that close action should be undone because you're not using `exec' and the file descriptor was created using the variable assignment syntax. The latter is what bash does now. > You've also explained what bash is doing that makes this untrue if the > command was an external command. Because you never open the file descriptor in the parent shell: redirections happen in the child. The child process in case 2 (and 4) can do what it wants with the file descriptor, and its view of the file descriptor is the same as case 1 (and 3). > I don't believe that this behaviour is *intended( to depend on the > non-obvious detail of whether or not the command is external. Why? There are plenty of things that depend on whether or not a command is builtin, or whether it's run in the parent shell. > > Given the coding pattern of wrapping external commands with functions that > re-invoke using bash "command"; this can lead to unpredictable behaviours > when such wrappers are active. > > e.g. openssl() { LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/extra" *command* > openssl "$@"; } > > If that function is defined, I get a handle leak*, if it isn't and main > openssl is called, I don't -- or from the other of view my handle got > closed without my knowledge, so I can't use it as I wish. > > Personally I would wish that "{var} internal" would also close the fd as it > does for numeric fd and for external {var} fd, because if I really wanted > to open an fd and have it hang around I would do a naked: exec {xxx}>&2 ; > type of thing. Sure. But there's not as good a reason to have that syntax otherwise. It's just syntactic sugar, a way for historical shells to use file descriptors greater than 9. > I also think that based on your description of what bash is doing, it might > be easier to fix by also closing in the parent, as I describe. > > It would bring full consistency and avoid hard to detect and hard to > code-around bugs. > > Ultimately, unless {var} external is intended to behave different to {var} > internal, then we have a consistency bug. The internal/external difference doesn't really have anything to do with the semantics of file descriptors or redirections per se; only that redirections are performed in the child. There are multiple variations in behavior depending on whether a command is executed in a subshell, and this is one of them. Ultimately, the difference is between cases 1 and 3 and retaining a handle to the file descriptor instead of closing it when the command finishes. Everything else is identical between the two commands. That was a design choice. I don't see changing it now. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRU c...@case.edu http://tiswww.cwru.edu/~chet/