webotronics has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I need to add a timeout for external calls, 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...

Code: ( perl )

1. use POSIX ":sys_wait_h"; 2. my $loop = 1; 3. $loop = $ARGV[0] if defined $ARGV[0]; 4. my $timeout = 10; 5. my $child = fork(); 6. unless ( $child ) { 7. # Child 8. exec( "perl count.pl $loop" ); 9. exit 0; 10. } 11. 12. sleep( $timeout ); 13. my $kid = waitpid( $child, WNOHANG ); 14. if( $kid != -1 ) { 15. print "The child is still running! Kill the process: $child. +..\n"; 16. kill( 9, $child ); 17. } 18. else { print "no timeout\n"; }
The external program count.pl, is simply a program that prints an iterator every second:

Code: ( perl )

1. my $loop = 1; 2. my $iterator = 1; 3. $loop = $ARGV[0] if defined $ARGV[0]; 4. for( ; $iterator <= $loop ; $iterator++ ) { 5. sleep( 1 ); 6. print "$iterator($$)...\n"; 7. }
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:

Code: ( perl )

1. local $SIG{ALRM} = sub { die "alarm\n" }; # NB \n required 2. alarm 10; 3. $child_pid = fork(); 4. if( $child_pid ) { 5. print "Child_pid = $child_pid\n"; 6. $pid2 = waitpid( $child_pid, 0 ); 7. } 8. elsif( $child_pid == 0 ) { 9. print "child pid= $$\n"; 10. exec( "ratlperl count.pl $x" ); 11. exit( 0 ); 12. }
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

Replies are listed 'Best First'.
Re: Problem to add a timeout to external calls on Win32
by sh1tn (Priest) on Dec 07, 2007 at 13:36 UTC
Re: Problem to add a timeout to external calls on Win32
by jrsimmon (Hermit) on Dec 07, 2007 at 15:42 UTC
Re: Problem to add a timeout to external calls on Win32
by ikegami (Patriarch) on Dec 07, 2007 at 17:06 UTC

    I only took a glimpse at your post since its totally unreadable. Put code in <c>...</c> tags. They'll even handle escaping special HTML characters for you.

    On of the problems you might be facing is getting the PID of the right process. You might be getting the PID of a shell used to launch the process. Create in Win32::Process will help you with that.