假设我有这个:
pipe(READ,WRITE);
$pid = fork();
if ($pid == 0) {
close(READ);
# do something that may be blocking
print WRITE "done";
close(WRITE);
exit(0);
} else {
close(WRITE);
$resp = <READ>;
close(READ);
# do other stuff
}
在这种情况下,孩子可能会无限期地挂起。有没有办法我可以在READ
读取一段时间(即超时),如果我什么都没有得到,我会假设孩子挂了? p>
答案 0 :(得分:1)
通常,在C或Perl中,您使用 select()来测试是否有可用的输入。如果您愿意,可以指定超时 0 ,但在下面的示例中使用 1秒。:
use IO::Select;
pipe(READ,WRITE);
$s = IO::Select->new();
$s->add(\*READ);
$pid = fork();
if ($pid == 0) {
close(READ);
# do something that may be blocking
for $i (0..2) {
print "child - $i\n";
sleep 1;
}
print WRITE "donechild";
close(WRITE);
print "child - end\n";
exit(0);
} else {
print "parent - $pid\n";
close(WRITE);
for $i (0..10) {
print "parent - $i\n";
# 1 second wait (timeout) here. Can be 0.
print "parent - ", (@r=$s->can_read(1))?"yes":"no", "\n";
last if @r;
}
$resp = <READ>;
print "parent - read: $resp\n";
close(READ);
# do other stuff
}
答案 1 :(得分:0)
我有没有办法从READ读取一段时间(即超时),如果我没有得到任何东西,我会假设孩子正在挂起而继续做父母?
当你分叉时,你正在使用两个完全独立的进程。您正在运行程序的两个单独副本。您的代码无法在程序中的父级和子级之间来回切换。你的节目是父母或孩子。
您可以在父级中使用alarm向您的父进程发送 SIGALRM 。如果我没记错的话,您可以设置$SIG{ALRM}
子程序,启动闹钟,进行读取,然后将alarm
设置为零以将其关闭。整件事需要包裹在eval
。
我很久以前就做过这个。出于某种原因,我记得标准系统读取不起作用。您必须使用sysread。有关更多帮助,请参阅Perl Signal Processing。