我通過open3文檔去了,這裏要說的是我無法理解的部分:爲什麼IPC :: Open3會死鎖?
If you try to read from the child's stdout writer and their stderr writer, you'll have problems with blocking, which means you'll want to use select() or the IO::Select, which means you'd best use sysread() instead of readline() for normal stuff.
This is very dangerous, as you may block forever. It assumes it's going to talk to something like bc, both writing to it and reading from it. This is presumably safe because you "know" that commands like bc will read a line at a time and output a line at a time. Programs like sort that read their entire input stream first, however, are quite apt to cause deadlock.
所以我嘗試了open3
希望能知道它更好。這是第一個嘗試:
sub hung_execute {
my($cmd) = @_;
print "[COMMAND]: $cmd\n";
my $pid = open3(my $in, my $out, my $err = gensym(), $cmd);
print "[PID]: $pid\n";
waitpid($pid, 0);
if(<$err>) {
print "[ERROR] : $_" while(<$err>);
die;
}
print "[OUTPUT]: $_" while (<$out>);
}
很有趣的是,我必須在這裏初始化$err
。
無論如何,這只是當我execute("sort $some_file");
給定$some_file
是一個包含超過4096個字符(限制我的機器)的文本文件時掛起。
然後我看着this常見問題,以下是我執行的新版本:
sub good_execute {
my($cmd) = @_;
print "[COMMAND]: $cmd\n";
my $in = gensym();
#---------------------------------------------------
# using $in, $out doesn't work. it expects a glob?
local *OUT = IO::File->new_tmpfile;
local *ERR = IO::File->new_tmpfile;
my $pid = open3($in, ">&OUT", ">&ERR", $cmd);
print "[PID]: $pid\n";
waitpid($pid, 0);
seek $_, 0, 0 for \*OUT, \*ERR;
if(<ERR>) {
print "[ERROR] : $_" while(<ERR>);
die;
}
print "[OUTPUT]: $_" while (<OUT>);
}
的sort
命令現在執行很好,但我想不出爲什麼。
[更新]閱讀@ tchrist的回答後,我讀IO::Select
,經過一些google搜索,想出了這個版本的execute
:
sub good_execute {
my($cmd) = @_;
print "[COMMAND]: $cmd\n";
my $pid = open3(my $in, my $out, my $err = gensym(), $cmd);
print "[PID]: $pid\n";
my $sel = new IO::Select;
$sel->add($out, $err);
while(my @fhs = $sel->can_read) {
foreach my $fh (@fhs) {
my $line = <$fh>;
unless(defined $line) {
$sel->remove($fh);
next;
}
if($fh == $out) {
print "[OUTPUT]: $line";
}elsif($fh == $err) {
print "[ERROR] : $line";
}else{
die "[ERROR]: This should never execute!";
}
}
}
waitpid($pid, 0);
}
這是工作的罰款,以及幾件事情現在變得更清晰了。但總體情況還是有點朦朧。
所以我的問題是:
- 這有什麼錯
hung_execute
? - 我猜
good_execute
因爲open3調用中的>&
而起作用。但是爲什麼和如何? - 此外,當我使用詞法變量(
my $out
而不是OUT
)作爲文件句柄時,good_execute
不起作用。它給出了這個錯誤:open3: open(GLOB(0x610920), >&main::OUT) failed: Invalid argument
。爲什麼這樣? - 似乎只有一個文件句柄可以在給定的時間寫入,而且如果我放棄持有資源的句柄,其他句柄就會繼續等待。我曾經認爲STDERR和STDOUT是獨立的流,並沒有共享任何資源。我想我的理解在這裏有點有缺陷。請給我一些指示。
我讀了'IO :: Select'模塊,並更新了我的問題... – Unos 2012-04-05 15:12:31
@Unos你有很多問題。你應該只問一個問題。我確實已經回答了最初的問題,但你又問了同樣的問題,就好像你沒有注意到的一樣。我想,回答所有新問題需要在每個程序中爲您的代碼的每一行添加一段或三段。要求某人的工作量很大,當然要超過一小時,而且最有可能要花費三個小時的免費工作。我今天沒有那個時間。請研究我已經說過的話,因爲我沒有看到它被沉沒。 – tchrist 2012-04-05 17:02:05
嗨@tchrist,我幾乎不想激怒你。在更新後我沒有刪除我之前的問題,因爲我認爲如果我這樣做,答案可能會丟失。我一定會更詳細地研究這一點。 – Unos 2012-04-06 04:05:03