Perl выбирает возвращение undef на sysread при использовании Windows, IPC::Open3 и IO::Socket->socketpair()

Я нашел этот пример (опубликованный @ikegami) способа использования IPC::Open3 в Windows с использованием сокетов. Проблема в том, что при запуске я получаю сообщение об ошибке . Существующее соединение было принудительно закрыто удаленным хостом на sysread, Команда выполняется, select работает правильно, но sysread получает undef вместо ожидаемого 0 для конца файла. Это поведение не одинаково для всех команд. Если я изменю команду на echo Hello World! это не вызывает ошибку. Есть идеи, что здесь происходит?

Вот код из примера:

use strict;
use warnings;

use IO::Select qw( );
use IPC::Open3 qw( open3 );
use Socket     qw( AF_UNIX SOCK_STREAM PF_UNSPEC );

print( "REMOVE ME: getting started\n" );

sub _pipe {
    socketpair($_[0], $_[1], AF_UNIX, SOCK_STREAM, PF_UNSPEC)
        or return undef;
    shutdown($_[0], 1);  # No more writing for reader
    shutdown($_[1], 0);  # No more reading for writer
    return 1;
}

sub _open3 {
    local (*TO_CHLD_R,     *TO_CHLD_W);
    local (*FR_CHLD_R,     *FR_CHLD_W);
    local (*FR_CHLD_ERR_R, *FR_CHLD_ERR_W);

    if ($^O =~ /Win32/) {
        _pipe(*TO_CHLD_R,     *TO_CHLD_W    ) or die $^E;
        _pipe(*FR_CHLD_R,     *FR_CHLD_W    ) or die $^E;
        _pipe(*FR_CHLD_ERR_R, *FR_CHLD_ERR_W) or die $^E;
    } else {
        pipe(*TO_CHLD_R,     *TO_CHLD_W    ) or die $!;
        pipe(*FR_CHLD_R,     *FR_CHLD_W    ) or die $!;
        pipe(*FR_CHLD_ERR_R, *FR_CHLD_ERR_W) or die $!;
    }

    my $pid = open3('>&TO_CHLD_R', '<&FR_CHLD_W', '<&FR_CHLD_ERR_W', @_);

    return ( $pid, *TO_CHLD_W, *FR_CHLD_R, *FR_CHLD_ERR_R );
}

# when i change the command to 'echo Hello World' it works...
my ($pid, $to_chld, $fr_chld, $fr_chld_err) =
    _open3('cmd /c "dir /s/b"');

my %objs;

my $in_sel  = IO::Select->new();
my $out_sel = IO::Select->new();

for my $fh ($fr_chld, $fr_chld_err) {
    my $obj = {
        buf => '',
    };
    $objs{ fileno($fh) } = $obj;
    $in_sel->add($fh);
}

close($to_chld);

while ($in_sel->count() + $out_sel->count()) {
    my ($ins, $outs) = IO::Select::select($in_sel, $out_sel, undef);

    for my $fh (@$ins) {
        my $obj = $objs{ fileno($fh) };
        our $buf; local *buf = \( $obj->{buf} );
        my $bytes_read = sysread($fh, $buf, 64*1024, length($buf));
        if (!$bytes_read) {
            warn("Error reading from child: $!\n")
                if !defined($bytes_read);
            $in_sel->remove($fh);
        }
    }

    for my $fh (@$outs) {
    }
}

waitpid($pid, 0);

print("STDOUT:\n$objs{ fileno( $fr_chld     ) }{buf}");
print("\n" );
print("STDERR:\n$objs{ fileno( $fr_chld_err ) }{buf}");

1 ответ

Решение

Я думаю это потому что shutdown был использован вместо чего-то вроде close, Звучит безопасно игнорировать.

grep $!{$_}, keys %! шоу ECONNRESETтак что просто поменяй

warn("Error reading from child: $!\n")
    if !defined($bytes_read);

в

warn("Error reading from child: $!\n")
    if !defined($bytes_read) && !$!{ECONNRESET};
Другие вопросы по тегам