将大型数据写入管道时进程挂起



我的Perl程序有一个挂起进程的问题,我想每当我向管道写入大量数据时,我都会将其隔离出来。

下面是我认为与我的程序相关的所有代码。当程序挂起时,它会挂在 ResponseConstructor.pm:print { $self->{writer} } $data; 的行上。

我已经测试了不同的数据大小,它似乎没有以确切的大小挂起。不过,随着大小的增加,这种情况可能会变得更有可能:32KB左右的大小有时有效,有时无效。每次我尝试 110KB 字符串时,它都失败了。

我相信我也排除了数据的内容作为原因,因为相同的数据有时会导致挂起,而其他时候则不然。

这可能是我以前第一次在程序中使用管道,所以我不确定接下来要尝试什么。有什么想法吗?

use POSIX ":sys_wait_h";
STDOUT->autoflush(1);
pipe(my $pipe_reader, my $pipe_writer);
$pipe_writer->autoflush(1);
my $pid = fork;
if ($pid) {
    #I am the parent
    close $pipe_writer;
    while (waitpid(-1, WNOHANG) <= 0){
        #do some stuff while waiting for child to send data on pipe
    }
    #process the data it got
    open(my $fh, '>', "myoutfile.txt");
    while ( my $line = <$pipe_reader>){
        print $fh $line;
    }
    close $pipe_reader;
    close $fh;
else {
    #I am the child
    die "cannot fork: $!" unless defined $pid;
    close $pipe_reader;
    my $response = ResponseConstructor->new($pipe_writer);
    if ([a condition where we want to return small data]){
        $response->respond('small data');
        exit;
    }
    elsif ([a condition where we want to return big data]){
        $response->respond('imagine this is a really big string');
    }
}

ResponseConstructor.pm:

package ResponseConstructor;
use strict;
use warnings;
sub new {
    my $class = shift;
    my $writer = shift;
    my $self = {
        writer => $writer
    };
    bless($self, $class);
    return($self);
}
#Writes the response then closes the writer (pipe)
sub respond {
    my $self = shift;
    my $data = shift;
    print { $self->{writer} } $data;
    close $self->{writer};
}

1;

您可能不应该在管道返回数据时忽略管道:您可以在管道上使用select(而不是waitpid(来查看在等待循环期间是否有任何数据要读取,但是如果您真的想要一个更大的管道缓冲区,以便您可以一次读取所有数据,您可以使用socketpair而不是管道,然后您可以使用setsockopt来制作缓冲区随心所欲。

最新更新