tags:

views:

145

answers:

2

I get a file descriptor leak when running the following code:

function get_fd_count() {
        local fds
        cd /proc/$$/fd; fds=( * ) # avoid a StackOverflow source colorizer bug
        echo "${#fds[@]}"
}

function fd_leak_func() {
        while : ; do
                echo ">> Current FDs: $(get_fd_count)"
                read retval new_state < <(set +e; new_state=$(echo foo); retval=$?; printf "%d %s\n" $retval $new_state)
        done
}

fd_leak_func

Tested on both 3.2.25 and 4.0.28.

This only happens when the loop is happening within a function; every time we return to top-level context, the extra file descriptors are closed.

Is this intended behavior? More to the point, are workarounds available?


Followup: After reporting to the bash-bug mailing list, this was confirmed as a bug. Chet indicated that a fix will be included in the next release (as of 4/17/2010).

+1  A: 

Putting a /bin/true at the end of the loop fixes it, but I don't know why or how, or why it happens in the first place.

Ignacio Vazquez-Abrams
I see it in versions 4.0.33(1)-release, 4.1.0(1)-release and 3.2.49(23)-release. It also seems to fix it if I put an `(exit 0)` "no-op" subshell at the end of the loop instead of `/bin/true` (which works for me as well).
Dennis Williamson
+1  A: 

Here's a simplified example:

$ fd_leaker() { while :; do read a < <(pwd); c=(/proc/$$/fd/*); c=${#c[@]}; echo $c; done; } 
$ fd_leaker

This one is not fixed by using /bin/true but it's mostly fixed by using (exit 0) But I get "bash: echo: write error: Interrupted system call" errors using that "fix" or if I use /bin/pwd instead of the builtin pwd.

It also seems to be specific to read. I tried grep . < <(pwd) > /dev/null and it worked properly. When I tried while read a; do :; done < <( pwd)

The extra file descriptors in the form of:

lr-x------ 1 user user 64 2010-04-15 19:26 39 -> pipe:[8357879]

I really don't think the runaway creation of them is intended, after all there's nothing recursive going on. I really don't see how adding something in the loop should fix things.

Dennis Williamson