Perl select 返回“坏文件描述符"错误 [英] Perl select return "bad file descriptor" error
问题描述
我正在尝试使用管道和 select
命令实现进程间通信.这是第一次尝试:
I am trying to implement inter process communication using pipes and the select
command. Here is a first try:
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;
}
输出为:
Running select..
Processing file descriptor 4
Got line: "Child 2 says: A"..
Running select..
Processing file descriptor 3
Got line: "Child 1 says: A"..
Running select..
Processing file descriptor 4
Got line: "Child 2 says: B"..
Select count: 1
Closed fh 2..
Running select..
Done.
问题是孩子 1 的最后一条消息丢失了得到了一行:孩子 1 说:B"
.
The problem is that the last message from child 1 is missing Got line: "Child 1 says: B"
.
我运行 strace prog.pl
给出:
select(8, [3 4], NULL, NULL, NULL) = -1 EBADF (Bad file descriptor)
在最后一个 select
调用..
on the last select
call..
推荐答案
$fh->close();
$sel->remove($fh);
您必须首先从选择中删除文件描述符,然后将其关闭.一旦关闭,它就不再有效(即 fileno($fh)
将返回 undef)并且无法删除.如果不能删除 select 仍然会尝试选择这个(无效的)文件描述符,导致 EBADF.
You must first remove the file descriptor from the select and then close it. Once it is closed it is no longer valid (that is fileno($fh)
will return undef) and cannot be removed. And if cannot be removed select will still try to select on this (invalid) file descriptor, causing EBADF.
这篇关于Perl select 返回“坏文件描述符"错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!