in reply to Re^3: Timeout and kill
in thread Timeout and kill

I don't see what you are doing with $result, but one way is to capture the process ID from the shell:

$pid = `command && echo $$` ;

I suggest you take a step back and start again with File::Find. I think you've overcomplicated your solution.

You might also try to prevent the OOM issue in the "solver" instead.

Replies are listed 'Best First'.
Re^5: Timeout and kill
by Eliya (Vicar) on Mar 21, 2012 at 02:33 UTC
    ...but one way is to capture the process ID from the shell:

    $pid = `command && echo $$` ;

    This wouldn't work.

    First (and least relevant), backticks interpolate the $$, so you'd get the PID of the Perl process here.  But even when fixing this using \$\$, you'd still not get the PID of the command, but that of the shell. And killing the shell does not necessarily also kill the command.  You could in theory try to fix the latter problems by using exec, i.e.

    $pid = `echo \$\$ && exec command` ;

    However, that still wouldn't work, because you wouldn't get at the $pid before the entire backticks command completed.  And in case of a timeout (where you would need the PID primarily), you'd get nothing at all:

    #!/usr/bin/perl -w use strict; my $pid; local $SIG{ALRM} = sub { die "Timeout (pid=$pid)\n"; }; my $command = "perl -e '<>'"; alarm 5; eval { $pid = `echo \$\$ && exec $command`; }; print $@; alarm 0; print "pid=$pid\n"; __END__ Use of uninitialized value $pid in concatenation (.) or string at ./96 +0632.pl line 7. Timeout (pid=) Use of uninitialized value $pid in concatenation (.) or string at ./96 +0632.pl line 18. pid=

    P.S.: contrary to what is implied elsewhere in the thread, alarm does by default not kill the subprocess behind the backticks in case of a timeout — as can easily be verified using ps.

      I am still struggling very much with killing the process once it has timed out. This is what I have:
      sub runFile2 { local($fileName, $timeout) = @_; my $child_pid; local $SIG{ALRM} = sub { $didTimeout=1; print OUTPUT "timeout"; print OUTPUT "-", $child_pid; kill 9, $child_pid; }; if ($child_pid = fork ) { # create child $didTimeout=0; alarm $timeout; $start=gettimeofday(); waitpid($child_pid, 0); # Wait for child to terminate alarm 0; $end=gettimeofday(); if($didTimeout==0) { print OUTPUT $end - $start; } else { kill 9, $child_pid; } } elsif (defined $child_pid) { $cmd = "$solver1 $fileName >> output.txt"; exec ($cmd); exit; } else { # Something terrible has happened, as fork failed die "Cannot fork!\n"; } }
      It may not be the best way because I've just been trying anything I can find. The code will timeout the function, but not kill it. Any suggestions? Help would be greatly appreciated. I've tried everything I can find online without success. Thanks!
        Oops I posted the wrong version of the code:
        sub runFile { local($fileName, $timelimit) = @_; my $child_pid; local $SIG{ALRM} = sub { $didTimeout=1; print OUTPUT "timeout"; print OUTPUT "-", $child_pid; kill $child_pid, 9; }; if ($child_pid = fork ) { # create child waitpid($child_pid, 0); # Wait for child to terminate } elsif (defined $child_pid) { alarm $timelimit; $cmd = "time $solver1 $fileName >> output.txt"; exec ($cmd); alarm 0; exit; } else { # Something terrible has happened, as fork failed die "Cannot fork!\n"; } }
        This code times out the function but allows it to still run in the background.
Re^5: Timeout and kill
by nelson64 (Initiate) on Mar 20, 2012 at 20:00 UTC
    I took some time to look into File::Find. I had come across this before but it appears I misunderstood it's functionality. Thanks for you help! This has gotten me working on the next part of the problem.