Perl select return";“错误的文件描述符”;错误
我正在尝试使用管道和Perl select return";“错误的文件描述符”;错误,perl,Perl,我正在尝试使用管道和select命令实现进程间通信。这里是第一次尝试: use warnings; use strict; use feature qw(say); use IO::Select; use IO::Handle; my @rh; my %childs; my $numChilds=2; $SIG{CHLD}='IGNORE'; #Reap childs automatically for my $i (1..$numChilds) { pipe(my $pread, my
select
命令实现进程间通信。这里是第一次尝试:
use warnings;
use strict;
use feature qw(say);
use IO::Select;
use IO::Handle;
my @rh;
my %childs;
my $numChilds=2;
$SIG{CHLD}='IGNORE'; #Reap childs automatically
for my $i (1..$numChilds) {
pipe(my $pread, my $pwrite);
push(@rh,$pread);
$pwrite->autoflush(1);
my $child = fork();
if ($child==0) {
runChild($i,$pwrite);
}
$childs{$pread->fileno()}={pid=>$child,id=>$i,i=>0};
}
my $sel = IO::Select->new( @rh );
while (1) {
say "Running select..";
my @ready = $sel->can_read;
last if (! @ready);
for my $fh (@ready) {
say "Processing file descriptor ".($fh->fileno());
chomp(my $line=<$fh>);
my $fd=$fh->fileno();
my $child=$childs{$fd}->{id};
say "Got line: \"$line\"..";
my $nmsg=($childs{$fd}->{i})+1;
if ($nmsg==2) {
$fh->close();
$sel->remove($fh);
say "Select count: ".($sel->count());
say "Closed fh $child..";
} else {
$childs{$fd}->{i}=$nmsg;
}
}
}
say "Done.";
sub someSeconds { return int(rand(4))+3; }
sub runChild {
my ($i, $pipe)=@_;
sleep (someSeconds());
print $pipe "Child $i says: A\n";
sleep (someSeconds());
print $pipe "Child $i says: B\n";
exit 0;
}
问题是,来自child 1的最后一条消息缺少get行:“child 1说:B”
我运行了strace prog.pl
,它给出了:
select(8, [3 4], NULL, NULL, NULL) = -1 EBADF (Bad file descriptor)
在最后一次通话中,选择call
$fh->close();
$sel->remove($fh);
您必须首先从select中删除文件描述符,然后将其关闭。一旦关闭,它将不再有效(即fileno($fh)
将返回undef),并且无法删除。如果无法删除,select仍将尝试在此(无效)文件描述符上进行选择,导致EBADF。好,但我不是刚刚这么做了吗?因为您正在执行一个$fh->close()
操作之前,您正在执行的是$sel->remove($fh)
操作将描述符从select中删除之前,您正在关闭它。一定是相反的方向。
$fh->close();
$sel->remove($fh);