Perl 父进程挂起,等待子进程读取标准定值



我有一个模拟tee命令的perl脚本,所以我可以将输出写入终端和日志文件。它的工作原理是这样的(错误检查和省略)。

$pid = open(STDOUT, '-|');
# Above is perl magic that forks a process and sets up a pipe with the
# child's STDIN being one end of the pipe and the parent's STDOUT (in
# this case) being the other.
if ($pid == 0)
{
    # Child. 
    # Open log file
    while (<STDIN>)
    {
       # print to STDOUT and log file
    }
    #close log files
    exit;
}
# parent
open STDERR, '>&STDOUT';
# do lots of system("...") calls
close STDERR;
close STDOUT;
exit;

这有时会挂起,并且如果您查看所述进程的进程和堆栈,父级总是挂在其中一个关闭中,等待子项退出,而子项挂起从文件中读取某些内容(必须是 STDIN,因为没有其他文件)。

我不知道如何处理这个问题。如果您从未连接到控制台的 shell 运行程序,则似乎会发生问题 - 在普通 shell 中运行脚本工作正常 - 并且该脚本中最近唯一更改的代码段是添加打开/关闭文件只是为了触摸它(这是在脚本到达这个"tee"代码之前)。

以前有没有人遇到过这样的问题和/或对我可以做些什么来解决这个问题有建议?谢谢。

好吧,经过一些实验,似乎直接打开STDOUT似乎至少是部分原因。我的代码现在读起来是这样的:

$pid = open($handle, '|-');
if ($pid == 0)
{
    # Child. 
    # Open log file
    while (<STDIN>)
    {
       # print to STDOUT and log file
    }
    #close log files
    exit;
}
# parent
open my $oldout, '>&STDOUT';
open my $olderr, '>&STDERR';
open STDOUT, '>&', $handle;
open STDERR, '>&', $handle;
# do lots of system("...") calls
open STDOUT, '>&', $oldout;
open STDERR, '>&', $olderr;
close $handle or die "Log child exited unexpectedly: $!n";
exit;

如果没有别的,看起来更干净(但仍然比我想要的更混乱,因为我不知道如果这些 dup 中的任何一个有错误该怎么办)。但我仍然不清楚为什么在代码的早期打开和关闭句柄会对这一点产生如此大的影响。

最新更新