Reputation:
Let's say I have this:
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
}
In this situation, it's possible for the child to hang indefinitely. Is there a way I can read from READ
for a certain amount of time (ie, a timeout) and if I don't get anything, I proceed in the parent with the assumption that the child is hanging?
Upvotes: 1
Views: 492
Reputation: 21
Typically, in C or Perl, you use select() to test if there is any input available. You can specify a timeout of 0 if you like, though used 1 second in the example below.:
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
}
Upvotes: 1
Reputation: 107040
Is there a way I can read from READ for a certain amount of time (ie, a timeout) and if I don't get anything, I proceed in the parent with the assumption that the child is hanging?
When you fork, you are working with two entirely separate processes. You're running two separate copies of your program. Your code cannot switch back and forth between the parent and child in your program. You're program is either the parent or the child.
You can use alarm in the parent to send a SIGALRM to your parent process. If I remember correctly, you set your $SIG{ALRM}
subroutine, start your alarm, do your read, and then set alarm
back to zero to shut it off. The whole thing needs to be wrapped in an eval
.
I did this once a long time ago. For some reason, I remember that the standard system read didn't work. You have to use sysread. See Perl Signal Processing for more help.
Upvotes: 0