Perl:通过 open() 而无需 close() 创建僵尸
问题是这样的: 我有一个守护进程,它从客户端获取请求,根据请求执行一个函数(来自某个模块)并向客户端返回答案。 在 fork() 之后,我关闭 STDIN、STDOUT 和 STDERR。 一项功能是检查 dmesg。为此,我通过以下方式获得 dmesg 输出 打开(DMESG,“/bin/dmesg |”)。我在读取后没有关闭这个 fh,因为我认为它会在函数完成后自动关闭。 但这并没有发生,每次调用 dmesg 都会得到一个僵尸。
如何重新初始化 Perl 的 STDIN/STDOUT/STDERR?我发现“关闭 STDOUT 而不是重新打开的问题是,如果您打开其他文件,它们可能会得到 fd 0,1 或 2 - 阻止您将来重新打开 STDOUT。”通过 jmanning2k 我认为这与此有关,但我不太明白。我希望有人可以向我解释一下。
我知道我可以避免这个问题,例如通过 qx(); 调用 dmesg;或者只是关闭 fh,但我想了解僵尸来自哪里。
Here is the problem:
I've a daemon which get requests from a client, executes a function (from some module) due to the request and returns an answer to the client.
After the fork() I close STDIN,STDOUT and STDERR.
One function is to check dmesg. For this I get the dmesg output through
open(DMESG, "/bin/dmesg |"). I don't close this fh after reading from it, because I thought that it would close automatically after the function finished.
But this doesn't happen and I get a zombie for each call of dmesg.
On How can I reinitialize Perl's STDIN/STDOUT/STDERR? I found "The problem with closing STDOUT instead of reopening is that if you open other files, they might get fd 0,1 or 2 - preventing you from reopening STDOUT in the future." by jmanning2k
And I think that it has something to do with it but I don't really get it. I hope that someone can explain it to me.
I know that I can avoid the the problem e.g. by calling dmesg via qx(); or simply closing the fh but I want to understand where the zombies are coming from.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
表单
打开管道并将其分配给动态作用域变量
DMESG</code>。动态作用域变量实际上“永远”存在于 Perl 中,只要看到
local
就会根据需要保存。如果您改为使用形式
lexical 文件句柄变量
$dmesg
将在范围退出时关闭,假设没有其他原因使其保持活动状态(即它没有传回或以其他方式存储在全局变量中)。The form
Opens the pipe and assigns it to the dynamically scoped variable
DMESG
. Dynamically scoped variables actually live "forever" in Perl, being saved as necessary whenever alocal
is seen.If you instead use the form
The lexical filehandle variable
$dmesg
will be closed on scope exit, assuming there's no other reason to keep it alive (i.e. it's not passed back or otherwise stored in a global variable).为此,句柄必须是词法的,这样它就可以正确地超出范围。
For this to work, the handle must be lexical, so it can fall properly out of scope.
问题与 Perl 的实现方式有关。下面是文件
doio.c
中函数Perl_do_openn
的一段代码:如果打开一个现有的文件句柄,该文件句柄将被
open() 关闭并重新打开
。正如您从上面的代码中看到的那样,STD*
句柄不会发生这种情况。因此 Perl 会打开下一个空闲句柄,而旧的句柄保持打开状态。The problem has to do with the way Perl is implemented. Here's a piece of code from the function
Perl_do_openn
in filedoio.c
:If you open an existing filehandle, the filehandle will be closed and reopened by
open()
. This doesn't happen withSTD*
handles, as you can see from the code above. So Perl takes the next free handle for opening and the older one remains open.