Bash文件描述符泄漏

5

在运行以下代码时,我遇到了文件描述符泄漏的问题:

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

已经在3.2.25和4.0.28上进行了测试。

只有在循环发生在函数内部时才会出现这种情况;每次返回到顶层上下文时,额外的文件描述符都会被关闭。

这是预期行为吗?更重要的是,是否有可用的解决方法?


跟进:在报告给bash-bug邮件列表后,确认这是一个错误。Chet表示将在下一个版本中包含修复(截至2010年4月17日)。


更奇怪的是,如果我在循环末尾放一个 true ,它会继续增加,但是放一个 /bin/true 就可以保持在 5。 - Ignacio Vazquez-Abrams
使用bashbug程序将其报告给新闻组,并查看维护者Chet Ramey的反馈意见。 - Dennis Williamson
仍然存在CentOS 6 bash 4.1.2(1)-release中的泄漏问题。 - clacke
在我的bash(如上所述的版本)中添加/bin/true无济于事,但添加(exit 0)有用。我猜测创建子shell会触发某些清理程序。 - clacke
3个回答

4
这是一个简化的例子:
$ fd_leaker() { while :; do read a < <(pwd); c=(/proc/$$/fd/*); c=${#c[@]}; echo $c; done; } 
$ fd_leaker

这个问题不能使用 /bin/true 来解决,但是大多数情况下可以使用 (exit 0) 解决。但如果我使用这种“解决”方法,或者使用内置的 pwd 替代 /bin/pwd,就会出现“bash: echo: write error: Interrupted system call”的错误。
这个问题似乎与 read 命令有关。我尝试使用命令 grep . < <(pwd) > /dev/null,它可以正常工作。但当我尝试 while read a; do :; done < <( pwd) 命令时,就会出现问题。
这个问题还涉及额外的文件描述符形式:
lr-x------ 1 user user 64 2010-04-15 19:26 39 -> pipe:[8357879]

我真的不认为这些的失控创造是有意的,毕竟没有递归发生。我真的不明白在循环中添加东西如何解决问题。


2

在循环末尾放置/bin/true可以解决问题,但我不知道为什么或者如何解决,也不知道为什么会出现这种情况。


我在版本4.0.33(1)-release、4.1.0(1)-release和3.2.49(23)-release中看到它。如果我在循环结束时放置一个“(exit 0)”“空操作”子shell而不是“/bin/true”也似乎可以修复它(这对我也有效)。 - Dennis Williamson

1

这似乎在bash-4.2中已经被修复。我特别测试了bash-4.2.28


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接