http://www.perlmonks.org?node_id=324176

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

Hi guys!

I have an external script that I run from my Perl script using system(). I need a timeout mechanism, that will wait a given time on the execution of the script. If the script isn't finished (returned to my perl script) until this timeout passes, the perl script will be back in control and continue from the SAME SPOT (display warning to screen and continue).
In any case failure/success in running the script in the given timeout, I want to continue from the same spot.

Can anyone help me with that one?

Thanks

Replies are listed 'Best First'.
Re: Timeout on script
by Abigail-II (Bishop) on Jan 26, 2004 at 17:30 UTC
    Here's something to start off with. Note that it's not finished and only tested with one trivial example.
    package Timed; use strict; use warnings; use Exporter (); our @ISA = qw /Exporter/; our @EXPORT = qw /timed_system/; sub timed_system { my $time = shift; my $pid; local $SIG {ALRM} = sub {kill 15, $pid or die "kill: $!"; die "Timeout!"}; # Just SIGTERM. eval { $pid = fork; die "Fork failed: $!" unless defined $pid; unless ($pid) { exec @_; die "Exec failed: $!"; } alarm $time; waitpid $pid => 0; }; die $@ if $@ && $@ !~ /^Timeout!/; } 1;

    Abigail

      Thanks for the post, but do you know where I can get an example for the fork-exec solution, since in perlipc manual pages they mentioned that using eval-die can leave zombies and I would like to avoid that.

      Thanks
        Thanks for the post, but do you know where I can get an example for the fork-exec solution,
        Did you actually bother to look at the code I posted?
        They mentioned that using eval-die can leave zombies
        As I said, the code I posted hasn't been finished yet. Work on it.

        Abigail

Re: Timeout on script
by Abigail-II (Bishop) on Jan 26, 2004 at 17:18 UTC
    It's not like you are the first one with this problem. The answer is: fork, exec, $SIG {ALRM}, eval, alarm, and wait.

    You might want to consult man perlipc.

    Abigail

Re: Timeout on script
by duff (Parson) on Jan 26, 2004 at 17:26 UTC

      The caveat is that you need to be running Win2K or later. The job concept doesn't exist in earlier versions.


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      Timing (and a little luck) are everything!

Re: Timeout on script
by Coruscate (Sexton) on Jan 26, 2004 at 20:24 UTC

    One that does not require the use of a fork:

    #!c:/perl/bin/perl -w $|++; use strict; sleep $ARGV[0] and exit if $ARGV[0]; eval { local $SIG{ALRM} = sub { die "timeout\n" }; alarm 4; # change to timeout length system 'perl', $0, 6; # command to execute alarm 0; }; warn "external command timed out: $@\n" if $@ eq "timeout\n"; print "continuing on, regardless of success/failure\n";

      The OP doesn't say one way or the other, but note that Abigail's kills the new process and Coruscate's does not.
Re: Timeout on script
by Roy Johnson (Monsignor) on Jan 26, 2004 at 17:25 UTC
    perldoc -f alarm

    The PerlMonk tr/// Advocate
Re: Timeout on script
by eyepopslikeamosquito (Archbishop) on Feb 03, 2004 at 06:05 UTC
      if you are trying to make alarm clock then you need a call back function for extra module. try to make a script that rotate the functions and check for its timeout. Again if you are trying to do something after reporting timeout.
      my $time_out = 5; my $flag = 1; while(1){ my $diff = time() - $starttime; if($diff >= $time_out){ print "already reached maximum timeout\n"; last; } if($flag){ printData(); $flag = 0; } sleep(1); } sub printData { print "i am running....\n"; }