There are various "issues" with your code — primarily the following two:
after the fork, you don't differentiate between the child and the parent process. This means you have two processes both doing the same thing (running the solver, etc.) — the child process with a $pid of zero, and the parent with a $pid unequal zero.
the backticks do fork/wait themselves under the hood, so the pid you're killing is not the solver process, as intended...
There are several ways to approach this. Personally, I'd probably use a piped open instead of the backticks. Something like this:
sub run_with_timeout { my ($cmd, $timeout) = @_; local $SIG{ALRM} = sub { die "Timeout\n"; }; my $out; if (my $pid = open my $pipe, "-|") { eval { alarm $timeout; @$out = <$pipe>; }; my $ok = $@ ne "Timeout\n"; alarm 0; if ($ok) { close $pipe; } else { kill 9, $pid; waitpid $pid, 0; } return $out; } else { exec $cmd; exit; } } my $out = run_with_timeout("$solver $file", $timeout); print defined($out) ? "output of solver:\n@$out" : "timed out";
P.S.: in case your solver command contains shell meta characters (such as 2>&1), it would be run via a shell. This means you'd have to modify the exec call to read:
exec "exec $cmd";
The second exec is executed by the shell, so it replaces itself with the solver command. It is required so that you kill the solver, not the shell.
In reply to Re: Timeout and kill
by Eliya
in thread Timeout and kill
by nelson64
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |