Perl:通过open()创建僵尸而不关闭()

时间:2010-12-15 15:03:25

标签: perl file-io filehandle zombie-process

问题在于: 我有一个守护进程,它从客户端获取请求,由于请求而执行一个函数(来自某个模块)并向客户端返回一个答案。 在fork()之后我关闭了STDIN,STDOUT和STDERR。 一个功能是检查dmesg。为此,我得到了dmesg输出 打开(DMESG,“/ bin / dmesg |”)。读完之后我没有关闭这个fh,因为我认为它会在函数完成后自动关闭。 但这不会发生,每次调用dmesg都会得到一个僵尸。

On How can I reinitialize Perl's STDIN/STDOUT/STDERR?我发现“关闭STDOUT而不是重新打开的问题是,如果你打开其他文件,它们可能会得到fd 0,1或2 - 阻止你将来重新打开STDOUT。”通过jmanning2k 而且我认为它与它有关,但我并没有真正理解它。我希望有人可以向我解释。

我知道我可以避免这个问题,例如通过qx()调用dmesg;或者只是关闭fh,但我想了解僵尸的来源。

3 个答案:

答案 0 :(得分:7)

表格

open DMESG, "/bin/dmesg|";

打开管道并将其分配给动态作用域变量DMESG。动态范围的变量实际上在Perl中“永久”存在,只要看到local,就会根据需要进行保存。

如果您改为使用表格

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

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

答案 1 :(得分:6)

  

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

为了使其工作,句柄必须是词法的,因此它可以正确地落在范围之外。

open my $dmesg, …

答案 2 :(得分:1)

问题与Perl的实现方式有关。以下是文件Perl_do_openn中函数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;
}

如果您打开现有的文件句柄,文件句柄将被open()关闭并重新打开。正如您从上面的代码中可以看到的那样,STD*句柄不会发生这种情况。因此,Perl将下一个空闲句柄打开,旧版本保持打开状态。