Perl:通过 open() 而无需 close() 创建僵尸

发布于 2024-10-07 10:14:08 字数 561 浏览 8 评论 0原文

问题是这样的: 我有一个守护进程,它从客户端获取请求,根据请求执行一个函数(来自某个模块)并向客户端返回答案。 在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

绝不服输 2024-10-14 10:14:08

表单

open DMESG, "/bin/dmesg|";

打开管道并将其分配给动态作用域变量DMESG<​​/code>。动态作用域变量实际上“永远”存在于 Perl 中,只要看到 local 就会根据需要保存。

如果您改为使用形式

open my $dmesg, "/bin/dmesg|";

lexical 文件句柄变量 $dmesg 将在范围退出时关闭,假设没有其他原因使其保持活动状态(即它没有传回或以其他方式存储在全局变量中)。

The form

open DMESG, "/bin/dmesg|";

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 a local is seen.

If you instead use the form

open my $dmesg, "/bin/dmesg|";

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).

薔薇婲 2024-10-14 10:14:08

open(DMESG, "/bin/dmesg |")
我在读取后没有关闭这个 fh,因为我认为它会在函数完成后自动关闭。

为此,句柄必须是词法的,这样它就可以正确地超出范围。

open my $dmesg, …

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.

For this to work, the handle must be lexical, so it can fall properly out of scope.

open my $dmesg, …
萌能量女王 2024-10-14 10:14:08

问题与 Perl 的实现方式有关。下面是文件 doio.c 中函数 Perl_do_openn 的一段代码:

fd = PerlIO_fileno(IoIFP(io));
if (IoTYPE(io) == IoTYPE_STD) {
    /* This is a clone of one of STD* handles */
    result = 0;
}
else if (fd >= 0 && fd <= PL_maxsysfd) {
    /* This is one of the original STD* handles */
    saveifp  = IoIFP(io);
    saveofp  = IoOFP(io);
    savetype = IoTYPE(io);
    savefd   = fd;
    result   = 0;
}

如果打开一个现有的文件句柄,该文件句柄将被 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 file doio.c:

fd = PerlIO_fileno(IoIFP(io));
if (IoTYPE(io) == IoTYPE_STD) {
    /* This is a clone of one of STD* handles */
    result = 0;
}
else if (fd >= 0 && fd <= PL_maxsysfd) {
    /* This is one of the original STD* handles */
    saveifp  = IoIFP(io);
    saveofp  = IoOFP(io);
    savetype = IoTYPE(io);
    savefd   = fd;
    result   = 0;
}

If you open an existing filehandle, the filehandle will be closed and reopened by open(). This doesn't happen with STD* handles, as you can see from the code above. So Perl takes the next free handle for opening and the older one remains open.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文