【问题标题】:Perl: creating zombies through open() without close()Perl:通过 open() 没有 close() 创建僵尸
【发布时间】:2011-05-25 23:30:42
【问题描述】:

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

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

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

【问题讨论】:

    标签: perl file-io filehandle zombie-process


    【解决方案1】:

    表格

    open DMESG, "/bin/dmesg|";
    

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

    如果您改为使用表单

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

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

    【讨论】:

      【解决方案2】:

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

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

      open my $dmesg, …
      

      【讨论】:

        【解决方案3】:

        问题与 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 使用下一个空闲句柄来打开,而旧的句柄仍然打开。

        【讨论】:

          猜你喜欢
          • 2014-09-30
          • 2013-11-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-12-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多