Perl:从后台线程关闭 open2 句柄
Perl: close open2 handle from a background thread
我只是想了解如何正确使用 open2
功能。
请参阅下面的示例。它适用于较小的 $max
,但自然地,如果我向 $hIn
写入足够长的时间,那么最终它会被阻塞,因为没有任何内容会连续读取输出上的数据。
use 5.26.0;
use IPC::Open2;
my $max = 100000;
my $pid = open2(my $hOut, my $hIn, "cat") || die "failed 'cat': $!";
{
my $cnt = 0;
#When $max is big (e.g. 100000) so the code below will get blocked
#when writing to $hIn
while ($cnt<$max) {say $hIn $cnt++;}
close($hIn) || say "can't close hIn";
}
while(<$hOut>) { print; }
close($hOut) || say "can't close hOut";
waitpid( $pid, 0 );
我能想到的唯一解决方案是启动另一个将在后台进行写入的线程。
使用下面的代码,我可以向 $hIn
中写入任意多的数据,并在主线程中读取它们,但 $hIn
似乎没有关闭。因此,while(<$hOut>)
在等待更多输出时将永远不会完成。
use 5.26.0;
use threads;
use IPC::Open2;
my $max = 100000;
my $pid = open2(my $hOut, my $hIn, "cat") || die "failed 'cat': $!";
my $thr = threads->create(sub {
my $cnt = 0;
while ($cnt<$max) {say $hIn $cnt++;}
#The close does not have any effect here (although no error is produced)
close($hIn) || say "can't close hIn";
});
#This outputs all the data written to $hIn but never leaves the loop...
while(<$hOut> ) { print; }
close($hOut) || say "can't close hOut";
$thr->join;
waitpid( $pid, 0 );
我的问题是:
- 假设我的线程方法没问题,我如何从后台线程关闭文件句柄?
- 如果不行(实际上
use threads
在 Perl 中是不鼓励的),那么有人可以提供一个 open2 的工作示例,它可以写入和读取大量数据而不会有被阻塞等待的风险reader 还是作家?
编辑:按照您的建议,使用 IPC::Run:
实现上述代码
use 5.26.0;
use IPC::Run qw/ run /;
my $max = 1000000;
run sub {
my $cnt = 0;
while ($cnt<$max) {say $cnt++;}
},
"|", "cat",
"|", sub {
while(<> ) {
print;
}
}
or die "run sub | cat | sub failed: $?";
它运行没有缺陷,代码可读性很强...很高兴了解了这个模块。感谢大家!
但是,我认为这个问题没有答案。如果不能直接使用 open2
编写此功能,那为什么还要存在并使人们感到困惑?也不能从不同的线程关闭文件句柄对我来说看起来像一个错误(当然是 - 关闭至少应该报告一个错误)。
- 您的程序已停止,因为它正在写入的管道已满。
- 通向
cat
的管道已满,因为 cat
停止读取它。
cat
因为写入的管道已满而停止。
- 来自
cat
的管道已满,因为您的程序没有从中读取数据。
所以你有两个程序在等待对方做某事。这是一个死锁。
低级别的解决方案是使用select
监控管道的两端。
高级解决方案是让 IPC::Run or IPC::Run3 为您完成这项艰巨的工作。
use IPC::Run qw( run );
my $cnt_max = 100000;
my $cnt = 0;
run [ "cat" ],
'<', sub { $cnt < $cnt_max ? $cnt++ . "\n" : undef };
我只是想了解如何正确使用 open2
功能。
请参阅下面的示例。它适用于较小的 $max
,但自然地,如果我向 $hIn
写入足够长的时间,那么最终它会被阻塞,因为没有任何内容会连续读取输出上的数据。
use 5.26.0;
use IPC::Open2;
my $max = 100000;
my $pid = open2(my $hOut, my $hIn, "cat") || die "failed 'cat': $!";
{
my $cnt = 0;
#When $max is big (e.g. 100000) so the code below will get blocked
#when writing to $hIn
while ($cnt<$max) {say $hIn $cnt++;}
close($hIn) || say "can't close hIn";
}
while(<$hOut>) { print; }
close($hOut) || say "can't close hOut";
waitpid( $pid, 0 );
我能想到的唯一解决方案是启动另一个将在后台进行写入的线程。
使用下面的代码,我可以向 $hIn
中写入任意多的数据,并在主线程中读取它们,但 $hIn
似乎没有关闭。因此,while(<$hOut>)
在等待更多输出时将永远不会完成。
use 5.26.0;
use threads;
use IPC::Open2;
my $max = 100000;
my $pid = open2(my $hOut, my $hIn, "cat") || die "failed 'cat': $!";
my $thr = threads->create(sub {
my $cnt = 0;
while ($cnt<$max) {say $hIn $cnt++;}
#The close does not have any effect here (although no error is produced)
close($hIn) || say "can't close hIn";
});
#This outputs all the data written to $hIn but never leaves the loop...
while(<$hOut> ) { print; }
close($hOut) || say "can't close hOut";
$thr->join;
waitpid( $pid, 0 );
我的问题是:
- 假设我的线程方法没问题,我如何从后台线程关闭文件句柄?
- 如果不行(实际上
use threads
在 Perl 中是不鼓励的),那么有人可以提供一个 open2 的工作示例,它可以写入和读取大量数据而不会有被阻塞等待的风险reader 还是作家?
编辑:按照您的建议,使用 IPC::Run:
实现上述代码use 5.26.0;
use IPC::Run qw/ run /;
my $max = 1000000;
run sub {
my $cnt = 0;
while ($cnt<$max) {say $cnt++;}
},
"|", "cat",
"|", sub {
while(<> ) {
print;
}
}
or die "run sub | cat | sub failed: $?";
它运行没有缺陷,代码可读性很强...很高兴了解了这个模块。感谢大家!
但是,我认为这个问题没有答案。如果不能直接使用 open2
编写此功能,那为什么还要存在并使人们感到困惑?也不能从不同的线程关闭文件句柄对我来说看起来像一个错误(当然是 - 关闭至少应该报告一个错误)。
- 您的程序已停止,因为它正在写入的管道已满。
- 通向
cat
的管道已满,因为cat
停止读取它。 cat
因为写入的管道已满而停止。- 来自
cat
的管道已满,因为您的程序没有从中读取数据。
所以你有两个程序在等待对方做某事。这是一个死锁。
低级别的解决方案是使用select
监控管道的两端。
高级解决方案是让 IPC::Run or IPC::Run3 为您完成这项艰巨的工作。
use IPC::Run qw( run );
my $cnt_max = 100000;
my $cnt = 0;
run [ "cat" ],
'<', sub { $cnt < $cnt_max ? $cnt++ . "\n" : undef };