Hi,
I need to add a timeout for external programs, as the external program sometimes never dies (it's a ClearQuest multisite call to the shipping server, that sometimes never ends, but simply hangs).
I have three different ways of forking the call, but none works. I send the one I believe most in...
-
use POSIX ":sys_wait_h";
-
my $loop = 1;
-
$loop = $ARGV[0] if defined $ARGV[0];
-
my $timeout = 10;
-
my $child = fork();
-
unless ( $child ) {
-
# Child
-
exec( "perl count.pl $loop" );
-
exit 0;
-
}
-
-
sleep( $timeout );
-
my $kid = waitpid( $child, WNOHANG );
-
if( $kid != -1 ) {
-
print "The child is still running! Kill the process: $child...\n";
-
kill( 9, $child );
-
}
-
else { print "no timeout\n"; }
-
-
The external program count.pl, is simply a program that prints an iterator every second:
-
my $loop = 1;
-
my $iterator = 1;
-
$loop = $ARGV[0] if defined $ARGV[0];
-
for( ; $iterator <= $loop ; $iterator++ ) {
-
sleep( 1 );
-
print "$iterator($$)...\n";
-
}
-
-
The idea is fine. After ten seconds, the mother process detects that the child process is still running, and tries to kill it.
And here is the strange thing!!!
The $child value (returned from the fork() command), is not the same as the $$ in the child process!!!
That means that the kill command is trying to kill another process (which in this case doesn't exist).
If I open another command tool window, and type in: perl -e "kill( 9, <child pid> )"
the child is killed.
Am I doing something wrong?
I tried also:
-
local $SIG{ALRM} = sub { die "alarm\n" }; # NB \n required
-
alarm 10;
-
$child_pid = fork();
-
if( $child_pid ) {
-
print "Child_pid = $child_pid\n";
-
$pid2 = waitpid( $child_pid, 0 );
-
}
-
elsif( $child_pid == 0 ) {
-
print "child pid= $$\n";
-
exec( "ratlperl count.pl $x" );
-
exit( 0 );
-
}
-
I do get an alarm signal after the timeout, but I don't have the correct pid here also. kill() doesn't work.
Any help would be appreciated very much.
Cheers,
/Richard