如何在 Perl 程序中查找打开的全局文件句柄
我刚刚发现一个问题,我必须关闭所有打开的文件句柄才能让我的 Apache cgi 脚本继续。我将问题追溯到 Parse::RecDescent。
#!/usr/bin/env perl
use strict;
use warnings;
use feature qw/say/;
$|++;
print "Content-Type: text/plain\n\n";
use Parse::RecDescent;
say "$$: pre-fork: ". time;
if(my $pid = fork) {
# parent
say "$$: return immediately: ". time;
}
else {
# child
say "$$: kicked off big process: ". time;
close STDIN;
close STDOUT;
close STDERR;
# close *{'Parse::RecDescent::ERROR'};
sleep 5;
}
我的问题是如何找到所有打开的包文件句柄?
我知道 fileno
会返回一个打开的文件句柄的计数器。 有没有办法对这些进行反向查找,或者通过其 fileno
计数器关闭文件句柄?
I just tracked down a problem where I had to close all open filehandles for my Apache cgi script to continue. I traced the problem to Parse::RecDescent.
#!/usr/bin/env perl
use strict;
use warnings;
use feature qw/say/;
$|++;
print "Content-Type: text/plain\n\n";
use Parse::RecDescent;
say "$: pre-fork: ". time;
if(my $pid = fork) {
# parent
say "$: return immediately: ". time;
}
else {
# child
say "$: kicked off big process: ". time;
close STDIN;
close STDOUT;
close STDERR;
# close *{'Parse::RecDescent::ERROR'};
sleep 5;
}
My question is how do I find all open package filehandles?
I know fileno
will return a counter for an open filehandle.
Is there a way to do a reverse lookup for these, or close filehandles by their fileno
counter?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在某些系统上,
“/proc/$$/fd/”返回的目录包含打开文件描述符的列表。您可以使用 POSIX::close 来关闭它们。
On some systems, the directory returned by
"/proc/$$/fd/"
contains the list of open file descriptors. You could usePOSIX::close
to close them.当出于 ikegami 的好奇心追踪 close-on-exec 详细信息时,我想我发现您需要做的就是关闭
STDIN
、STDOUT
和STDERR< /code> 自己,如果您只是执行另一个进程:
当然,如果您的长期任务不需要
execve(2)
调用来运行,那么 close-on-exec 标志将不会'对你一点帮助都没有。这完全取决于sleep 5
的替代品。When tracking down the close-on-exec details for ikegami's curiosity, I think I found that all you need to do is close
STDIN
,STDOUT
, andSTDERR
yourself if you are simply executing another process:Of course, if your long-lived task does not require an
execve(2)
call to run, then the close-on-exec flag won't help you at all. It all depends upon whatsleep 5
is a stand-in for.您可以向下浏览包树:
You can descend through the package tree:
使用保留其创建的所有句柄列表的版本来全局覆盖
open
怎么样?像这样的事情可能是一个开始:这应该捕获所有全局句柄,甚至任何已创建但从未清理过的词法句柄(由于循环引用或其他原因)。
如果您将此覆盖(
BEGIN
块)放在对use Parse::RecDescent
的调用之前,那么它将覆盖对open
的调用,模块使.What about globally overriding
open
with a version that keeps a list of all of the handles it creates? Something like this could be a start:This should catch all of the global handles, and even any lexical handles that got created but were never cleaned up (due to circular references or other reasons).
If you place this override (the
BEGIN
block) before the call touse Parse::RecDescent
then it will override the calls toopen
that the module makes.我最终使用了@ikegami的建议,但我对@Axeman的方法感兴趣。这是一个简化版本。
I ended up using @ikegami's suggestion but I was interested in @Axeman's method. Here is a simplified version.