bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: eval doesn't close file descriptor?


From: Matei David
Subject: Re: eval doesn't close file descriptor?
Date: Wed, 13 Feb 2013 12:44:22 -0500

Another thing I tried was to open a fd with <() and use it later in a shell
function. Surprisingly, the fd disappears (is closed) if the shell executes
something unrelated in subshell:

$ bash -c 'xxx () { echo "got arg: $1" >&2; ls -gG /proc/$BASHPID/fd >&2;
(echo "subprocess" >&2); ls -gG /proc/$BASHPID/fd >&2; cat $1; }; . lfd.sh;
xxx <(echo "hi")'
got arg: /dev/fd/63
total 0
lrwx------ 1 64 Feb 13 12:28 0 -> /dev/pts/9
lrwx------ 1 64 Feb 13 12:28 1 -> /dev/pts/9
lrwx------ 1 64 Feb 13 12:28 2 -> /dev/pts/9
lr-x------ 1 64 Feb 13 12:28 63 -> pipe:[5474849]
lr-x------ 1 64 Feb 13 12:28 8 -> /proc/4520/auxv
subprocess
total 0
lrwx------ 1 64 Feb 13 12:28 0 -> /dev/pts/9
lrwx------ 1 64 Feb 13 12:28 1 -> /dev/pts/9
lrwx------ 1 64 Feb 13 12:28 2 -> /dev/pts/9
lr-x------ 1 64 Feb 13 12:28 8 -> /proc/4520/auxv
cat: /dev/fd/63: No such file or directory
$

Note how 63 is open before '(echo)' and closed after. Is this expected?


On Wed, Feb 13, 2013 at 12:06 PM, Matei David <matei.david@gmail.com> wrote:

> Thank you for the explanation.
>
>
> On Tue, Feb 12, 2013 at 8:32 PM, Chet Ramey <chet.ramey@gmail.com> wrote:
>
>> On 2/12/13 11:40 AM, Pierre Gaston wrote:
>> > On Tue, Feb 12, 2013 at 6:07 PM, Matei David <matei.david@gmail.com>
>> wrote:
>> >
>> >> Ok, but I see the same behaviour when eval runs in a subshell:
>> >>
>> >> $ bash -c 'llfd () { echo "pid:$BASHPID" >&2; ls -l /proc/$BASHPID/fd/
>> >>> &2; }; x=3; eval "exec $x>/dev/null"; llfd; echo | eval "llfd $x>&-"'
>> >> [same output, fd 10 open, pointing to /dev/null, even though it's a
>> >> subshell]
>> >>
>> >
>> > eval runs in a subshell, but it's the same thing inside this subshell.
>> > eg you could have: echo | { eval "llfd "$x>&-"; echo blah >&3; }
>> >
>> > Bash could optimize this once it realizes there's only one command, but
>> > it's probably not that simple to implement.
>>
>> The basic flow is like this for any builtin command or shell function that
>> has a redirection (let's choose 'llfd 3>&-').
>>
>> 1.  The redirection is performed in the current shell, noting that it
>>     should be `undoable'.  That takes three steps:
>>
>> 1a. In this case, since fd 3 is in use, we dup it (to fd 10) and mark fd
>>     10 as close-on-exec.  We add a separate redirection to an internal
>>     list  that basically says "close fd 10".  Then we add another
>>     redirection to the front of the same internal list that says "dup fd
>>     10 back to fd 3".  Let's call this list "redirection_undo_list".  We
>>     will use it to restore the original state after the builtin or
>>     function completes.
>>
>> 1b. Take the first redirection from step 1a and add it to a separate
>>     internal list that will clean up internal redirections in the case
>>     that exec causes the redirections to be preserved, and not undone.
>>     Let's call this list "exec_redirection_undo_list".
>>
>> 1c. Perform the redirection.  Here, that means close fd 3.
>>
>> [perform step 1 for each redirection associated with the command]
>>
>> 2.  If we're running the exec builtin, throw away the list from 1a.  If
>>     we're not running the exec builtin, throw away the list from 1b.  Save
>>     a handle to the list we didn't discard.
>>
>> 3.  Run the function or builtin.
>>
>> 4.  Take the list saved in step 2 and perform the redirections to
>>     restore the previous state.  Here, that means we dup fd 10 back to fd
>>     3, then close fd 10.
>>
>> If you look at the steps, it should be clear why fd 10 is still open when
>> llfd executes.
>>
>> Bash `cheats' when running builtins or shell functions in pipelines or
>> other subshells.  It knows it's already going to be in a child process
>> when it performs the redirections, so it doesn't bother setting up the
>> structures to undo them.
>>
>> Chet
>>
>> --
>> ``The lyf so short, the craft so long to lerne.'' - Chaucer
>>                  ``Ars longa, vita brevis'' - Hippocrates
>> Chet Ramey, ITS, CWRU    chet@case.edu
>> http://cnswww.cns.cwru.edu/~chet/
>>
>
>


reply via email to

[Prev in Thread] Current Thread [Next in Thread]