http://qs1969.pair.com?node_id=266703

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

I know this has been asked a couple of times before, but please bear with me. I'd like to be able to run shell commands (system() or qx()) that time-out after a given time, something like:
$exit = &command( "/bin/snore", 60 );
I pretty new to the world of pipe/fork/exec stuff, so please excuse any ignorance!

I fould this in perlipc:
eval { local $SIG{ALRM} = sub { die "alarm clock restart" }; alarm 10; flock(FH, 2); # blocking write lock alarm 0; }; if ($@ and $@ !~ /alarm clock restart/) { die }
Along with the quote:

           If the operation being timed out is system() or qx(), this technique is liable to generate zombies. If this matters to you, you'll need to do your own fork() and exec(), and kill the errant child process.

So after a bit of research i came up with this:
#! /usr/bin/perl use strict; my $exit = &command( "sleep 4; exit 99;", 1 ); if(! defined( $exit ) ) { print "error: command timed-out\n" } else { print "yay, it worked, exit: $exit\n" } sub command { my( $command, $timeout ) = @_; my $pid; eval { local $SIG{ALRM} = sub { die }; if( $pid = fork ) { alarm $timeout } else { exec( $command ) || die( "Couldn't exec $comma +nd" ) } waitpid( $pid, 0 ); alarm 0; }; if( $@ ) { return undef } else { return $? / 256 } }
  • fork... check
  • exec... check
  • kill... ? oops, where do i do this?

    Am i still breeding zombies? And how do i go about capturing output? Thanks.

    - ><iper


    my JAPH: print"Just another Perl hacker\n"; # ^ look, no space! pretty tricky hey?