I created a script in perl to run programs with a timeout. If the program being executed takes longer then the timeout than the script kills this program and returns the message "TIMEOUT".
The script worked quite well until I decided to redirect the output of the executed program.
When the stdout and stderr are being redirected, the program executed by the script is not being killed because it has a pid different than the one I got from fork.
It seems perl executes a shell that executes my program in the case of redirection.
I would like to have the output redirection but still be able to kill the program in the case of a timeout.
Any ideas on how I could do that?
A simplified code of my script is:
#!/usr/bin/perl
use strict;
use warnings;
use POSIX ":sys_wait_h";
my $timeout = 5;
my $cmd = "very_long_program 1>&2 > out.txt";
my $pid = fork();
if( $pid == 0 )
{
exec($cmd) or print STDERR "Couldn't exec '$cmd': $!";
exit(2);
}
my $time = 0;
my $kid = waitpid($pid, WNOHANG);
while ( $kid == 0 )
{
sleep(1);
$time ++;
$kid = waitpid($pid, WNOHANG);
print "Waited $time sec, result $kid\n";
if ($timeout > 0 && $time > $timeout)
{
print "TIMEOUT!\n";
#Kill process
kill 9, $pid;
exit(3);
}
}
if ( $kid == -1)
{
print "Process did not exist\n";
exit(4);
}
print "Process exited with return code $?\n";
exit($?);
Thanks for any help.
Try changing $cmd
from
my $cmd = "very_long_program 1>&2 > out.txt";
to
my $cmd = "exec very_long_program 1>&2 > out.txt";
The exec
will tell the shell that gets spawned by perl to replace itself with very_long_program, rather than running very_long_program as a child.
(The reason perl spawns a shell in this case is because $cmd
contains the redirect characters - and perl doesn't know how to handle them itself. An alternative way of solving the problem is to do the redirection in perl itself after the fork()
but prior to calling exec()
- but that's slightly trickier, so try the exec
workaround first!)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With