[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: fd leak with {fd}>
From: |
Dan Douglas |
Subject: |
Re: fd leak with {fd}> |
Date: |
Sat, 01 Dec 2012 00:00:10 -0600 |
User-agent: |
KMail/4.8.3 (Linux/3.4.6-pf+; KDE/4.8.3; x86_64; ; ) |
On Monday, November 26, 2012 11:57:33 AM Chet Ramey wrote:
> On 11/26/12 8:41 AM, Pierre Gaston wrote:
> > On Mon, Nov 26, 2012 at 3:37 PM, Chet Ramey <chet.ramey@case.edu
> > <mailto:chet.ramey@case.edu>> wrote:
> >
> > On 11/23/12 2:04 AM, Pierre Gaston wrote:
> > > It seems rather counter intuitive that the fd is not closed after
leaving
> > > the block.
> > > With the normal redirection the fd is only available inside the block
> > >
> > > $ { : ;} 3>&1;echo bar >&3
> > > -bash: 3: Bad file descriptor
> > >
> > > if 3 is closed why should I expect {fd} to be still open?
> >
> > Because that's part of the reason to have {x}: so the user can handle the
> > disposition of the file descriptor himself.
> >
> > .
> > I don't see any difference between 3> and {x}> except that the later free
> > me from the hassle of avoid conflicting fd
>
> That's not really an issue. Bash goes to great effort to allow users to
> specify fds it is already using internally.
>
> The user/shell programmer getting a handle to the fd is one benefit. The
> ability to use those named fds in operators that don't allow words (e.g.
> variable expansions) to replace the explicit file descriptor number is
> another.
>
> David Korn beat all of us in implementing this feature (we first began
> discussing it in 2005). I should ask him if he has additional insight.
>
> Chet
>
I believe one of the motivations for named FDs other than automatic FD
allocation, and the reason they remain open, was probably to deal with
organizing and grouping coprocesses so that you could follow the variable
names rather than the FDs directly due to the somewhat awkward way they are
manipulated.
ksh, mksh, and zsh have almost the same system (except the Zsh "coproc"
pipeline modifier replaces Ksh's "|&" list operator) in which you start with
an "anonymous coproc" that can only be accessed indirectly through "read -p"
and "print -p", until moving the current coproc to a named FD with the special
"&p" redirects. After that, and you have a handle on the real FD, you can open
a new anonymous coproc and begin interacting with the others through "read -u"
and "print -u" instead. Basically:
Bash:
coproc { ...; }; read -ru "${COPROC}"
Everybody else:
{ ...; } |& { read -ru "$COPROC"; } {COPROC[0]}<&p {COPROC[1]}>&p
I suppose the idea was that you could have collections of coprocs organized
into arrays held open until you're finished with them. Bash does it without
adding all that extra syntax, so the FD assignment feature is less important,
with the downside being there are a bunch of incompatible conflicts like the
"|&" pipe and "read -p" (unnecessary features IMO, but not a big deal).
One potential gotcha in Bash is that RETURN traps execute while exposed to the
fds that were redirected during the call to the function, not to the
definition. I don't know if that's intentional or whether most people are
aware that both sets of redirects are active until returning even if a
redirect to the definition hides another made to the call. Since you can only
access local variables from a RETURN trap, but the visible FDs are a
combination of redirects held open from a execs or named FD assignments, plus
redirects to the function call, it could be easy to be surprised if relying
upon RETURN to close the right FD especially if variable names from different
scopes conflict.
$ bash -s <<\EOF
f() {
trap 'trap - RETURN; cat "/dev/fd/$x" -; exec {x}<&-' RETURN
local x
: <<<inner {x}<&0
cat "/dev/fd/$x" -
} <<<middle
f <<<outer
EOF
inner
middle
inner
outer
--
Dan Douglas
- Re: fd leak with {fd}>,
Dan Douglas <=