readline挂在手动管道上

时间:2018-11-19 10:29:36

标签: perl posix

我正试图消除open的魔力变体:

# magic-fork.pl
if (open my $fh, '-|') { # fork self, make new fd for reading, attach child STDOUT to it
    STDOUT->say('parent getpid: ', $$);
    STDOUT->say('parent STDOUT->fileno: ', STDOUT->fileno);
    STDOUT->say('parent $fh->fileno: ', $fh->fileno);
    while (my $line = $fh->getline) {
        STDOUT->print('parent readline from child: ', $line);
    }
} else {
    STDOUT->say('child getpid: ', $$);
    STDOUT->say('child STDOUT->fileno: ', STDOUT->fileno);
}

它运行并完成。

# plain-fork.pl
pipe my $r, my $w;
if (fork) {
    STDOUT->say('parent getpid: ', $$);
    STDOUT->say('parent STDOUT->fileno: ', STDOUT->fileno);
    STDOUT->say('parent $r->fileno: ', $r->fileno);
    STDOUT->say('parent $w->fileno: ', $w->fileno);
    while (my $line = $r->getline) {
        STDOUT->print('parent readline from child: ', $line);
    }
} else {
    $w->say('child getpid: ', $$);
    $w->say('child $r->fileno: ', $r->fileno);
    $w->say('child $w->fileno: ', $w->fileno);
    $w->say('child STDOUT->fileno: ', STDOUT->fileno);
}

该程序意外挂起。

我试图无济于事:

  • 调用$ w-> autoflush(1)
  • 显式关闭手柄
  • 显式出口
  • POSIX :: dup2 $ w到STDOUT
  • 检查strace -ff以查看是否错过了关键的系统调用

出什么问题了?

1 个答案:

答案 0 :(得分:3)

您在pipe之前fork(类似于此类IPC),因此两个进程都具有读取和写入文件描述符的开放副本,因此父级中的读取循环只会阻止等待更多输入,这些输入永远不会从仍处于打开状态的写入端发出。

子进程需要close $r;,父进程需要close $w;在各自块的开始处(或在您打印出这些句柄的文件描述符之后)。