in reply to Need Function for Timing out shell commands

Problem is i need the exit code from the shell command, so i can't change the code to fork/exec

There is no such limitation when using fork/exec. The waitpid built-in lets you retrieve the exit status of the child.

update: if you want to get the output from the program, you would like to launch the process using open:

my $pid = open my $fh, '-|', @cmd or die "open failed $!";
And then use a select loop to read from $fh while checking that it does not time out or otherwise send a signal to the process.

Replies are listed 'Best First'.
Re^2: Need Function for Timing out shell commands
by Anonymous Monk on Sep 15, 2011 at 16:55 UTC

    Ok let me explain it clearer. i've a main perl program which loops and execute commands (run's as a daemon), so when i execute with `cmd....` system and so so on i become zombies...... excample prog what i call

    test.pl #!/usr/bin/perl $status='OK'; print $status; 1; test2.pl #!/usr/bin/perl $status='124455566345'; print $status; 1; so here i get zombies, problem is i need the print $status; in daemon.pl, that can be ascii strings or numerics.... daemon.pl #!/usr/bin/perl while(1){ my $command='test1.pl or test2.pl'; my $status; eval { local $SIG{ALRM} = sub { die("dead\n"); }; alarm 2; my $status=`$command`; alarm(0); # turn off the alarm clock }; if($@){ if($@ eq "dead\n"){ $status='Timeout'; }else{ chomp($status); } } #do something with my $status..... sleep(5); }
      Using alarm to leave from `$cmd` prematurely leaves zombies as it jumps over the waitpid call inside that reaps the child process.
      # untested! my $pid = open my $out, '-|', $cmd or die "Open failed: $!"; local $INT{CHLD} = sub {}; my $fileno = fileno $out; my $start = time; my $str = ''; my $timedout = 0; while (1) { my $v = ''; vec($v, $fileno, 1) = 1; if (select($v, undef, undef, 1) > 0) { if (vec($v, $fileno, 1)) { sysread $v, $str, 1024, length $v or last; } } if (time - $start > $timeout) { $timedout = 1; kill INT => $pid } close ($out); print "timed out: $timedout\noutput: $str\n";