我想使用IPC :: Run通过孩子的STDIN,STDOUT和STDERR(启动,泵,完成)与孩子进行交流。它似乎有效。
我想知道如何检测
答案 0 :(得分:3)
pump
针对错误抛出die
,或者在所有已完成的活动完成后调用" 1>}时将其消息写入STDERR
。 #34;请在ROUTINES部分和pump
之前查看。如果孩子退出,第二种情况就会发生。因此,将pump
调用封装在eval
中,并将警告转换为die
以捕获这两种情况
if ($talk_to_child)
{
eval {
local $SIG{__WARN__} = sub { die "pump WARNING: @_" };
pump $harness;
};
if ($@) {
print $@;
$talk_to_child = 0;
};
}
# ... and eval {} for finish()
但是这一点并没有削减它:当父母试图写一个退出它的孩子时会得到一个SIGPIPE
,它会直接终止这个过程。当孩子关闭流并且父尝试写时,情况也是如此。因此,还要为SIGPIPE
$SIG{PIPE} = sub {
say "$_[0]: $!";
$talk_to_child = 0; # global
};
以便父母幸存SIGPIPE
。 <{1}}因为eval
投掷而仍然需要pump
。
这些一起照顾我提出的所有测试,实际上就像他们的立场一样。仍然需要处理程序和eval
中的一些处理来区分感兴趣的案例(如果需要)。
如果这加起来太多,另一种方法是在每次通话前检查。请参阅this post以获取单行检查(包含在子单元格中):( 1)孩子是否正在运行,使用result
,以及(2)&#34; 是否有开放I / O渠道或活动流程&#34;,使用pumpable
。
我认为你想要两者,并且还要投入SIGPIPE
处理程序。这应该涵盖它。
我在这里不能更具体,因为这个问题并没有提供具体细节。
答案 1 :(得分:1)
更新:感谢@zdim提醒我查看SIGPIPE
信号。以下是我的答案更新,同时还会检查SIGPIPE
:
我使用start
,pump
和finish
进行了简单的测试。这是我使用的主要脚本p.pl
:
use feature qw(say);
use strict;
use warnings;
use IPC::Run;
my $child_in;
my $child_out;
my $child_err;
my $child_name = shift;
my $harness = eval {
IPC::Run::start [ $child_name ], \$child_in, \$child_out, \$child_err;
};
if ( $@ ) {
chomp $@;
die "Caught exception: '$@'";
}
for (1..2) {
$child_in = "Joe$_\n";
say "Parent sleeping for 1 second..";
sleep 1;
eval {
local $SIG{PIPE} = sub {
die "Parent received SIGPIPE. "
. "Child is either dead or has closed its input pipe\n";
};
say "Sending data to child..";
my $result = $harness->pump;
say "IPC::Run::pump() returned: ", $result ? "TRUE" : "FALSE";
};
if ( $@ ) {
chomp $@;
say "IPC::Run::pump() failed: '$@'";
last;
}
say "\$child_in = '$child_in'";
say "\$child_out = '$child_out'";
}
say "Finishing harness..";
my $res = eval {
local $SIG{PIPE} = sub {
die "Parent received SIGPIPE. "
. "Child is either dead or has closed its input pipe\n";
};
$harness->finish;
};
if ( $@ ) {
chomp $@;
die "IPC::Run::finish() failed: '$@'\n";
}
printf "IPC::Run::finish() returned: '%s'\n", $res ? "TRUE" : "FALSE";
chomp $child_out;
say "STDOUT from child: '$child_out'";
chomp $child_err;
say "STDERR from child: '$child_err'";
say "Child returned exit code: ", $harness->result;
say "Parent exited normally.."
我使用了三种不同的子脚本:
<强> child.pl 强>:
#! /usr/bin/env perl
use feature qw(say);
use strict;
use warnings;
my $reply = <STDIN>;
chomp $reply;
say "Hello $reply";
my $reply2 = <STDIN>;
chomp $reply2;
say "Got second reply: $reply2";
exit 0;
并输出:
$ p.pl child.pl
Parent sleeping for 1 second..
Sending data to child..
IPC::Run::pump() returned: TRUE
$child_in = ''
$child_out = ''
Parent sleeping for 1 second..
Sending data to child..
IPC::Run::pump() returned: TRUE
$child_in = ''
$child_out = ''
Finishing harness..
IPC::Run::finish() returned: 'TRUE'
STDOUT from child: 'Hello Joe1
Got second reply: Joe2'
STDERR from child: ''
Child returned exit code:
Parent exited normally..
<强> child2.pl 强>:
#! /usr/bin/env perl
use feature qw(say);
use strict;
use warnings;
my $reply = <STDIN>;
chomp $reply;
say "Hello $reply";
die "Child exception\n";
并输出:
$ p.pl child2.pl
Parent sleeping for 1 second..
Sending data to child..
IPC::Run::pump() returned: TRUE
$child_in = ''
$child_out = ''
Parent sleeping for 1 second..
Sending data to child..
IPC::Run::pump() failed: 'Parent received SIGPIPE. Child is either dead or has closed its input pipe'
Finishing harness..
IPC::Run::finish() failed: 'Parent received SIGPIPE. Child is either dead or has closed its input pipe'
<强> child3.pl 强>:
#! /usr/bin/env perl
use strict;
use warnings;
close \*STDIN;
close \*STDOUT;
close \*STDERR;
sleep 5;
exit 2;
并输出:
$ p.pl child3.pl
Parent sleeping for 1 second..
Sending data to child..
IPC::Run::pump() failed: 'ack Parent received SIGPIPE. Child is either dead or has closed its input pipe'
Finishing harness..
IPC::Run::finish() failed: 'Parent received SIGPIPE. Child is either dead or has closed its input pipe'
因此,对于这些测试,似乎SIGPIPE
信号可用于检查子项是否处于活动状态或已关闭其输入管道。请注意,如果您在孩子退出后尝试呼叫pump()
,则孩子的上一个输出会丢失,请参阅child2.pl
示例。