crypto9294
crypto9294

Reputation: 171

Process hanging -SIGALRM not delivered- Perl

I have a command that I'm executing using OPEN with pipe, and I want to set a timeout of 10 seconds and have the sub process aborted if the execution time exceeds this. However, my code just causes the program to hang- Why is my ALARM not getting delivered properly?

my $pid = 0;
my $cmd = "someCommand";
print "Running Command # $num";
eval {
    local $SIG{ALRM} = sub {                    
        print "alarm \n";
        kill 9, $pid;
    };              
    alarm 10;
    pid = open(my $fh, "$cmd|");
    alarm 0;
};
if($@) {
    die unless $@ eq "alarm \n";
} else {
    print $_ while(<$fh>);
}

EDIT:

So From the answers below, This is what I have:

my $pid = open(my $fh, qq(perl -e 'alarm 10; exec \@ARGV; die "exec: $!\n" ' $cmd |));
print $_ while(<$fh>);

But this print ALARM CLOCK to the console when the alarm times out...whereas I dont specify this anywhere in the code...how can I get rid of this, and where would I put the custom alarm event handler?

Thanks!

Upvotes: 2

Views: 1396

Answers (2)

pilcrow
pilcrow

Reputation: 58524

I want to set a timeout of 10seconds and have the sub process aborted if the execution time exceeds this

A different approach is to set the alarm on the subprocess itself, with a handy scripting language you already have:

my $cmd = "someCommand";
my $pid = open(my $child_stdout, '-|',
   'perl', '-e', 'alarm 10; exec @ARGV; die "exec: $!"', $cmd);
...

Your child process will initially be perl (well, the shell and then perl), which will set an alarm on itself and then exec (replace itself with) $someCommand. Pending alarms, however, are inherited across exec()s.

Upvotes: 3

mob
mob

Reputation: 118595

All your code is doing is setting a 10 second timeout on the open call, not on the whole external program. You want to bring the rest of your interaction with the external command into the eval block:

eval {
    local $SIG{ALRM} = sub {                    
        print "alarm \n";
        kill 9, $pid;
    };              
    alarm 10;
    $pid = open(my $fh, "$cmd|");
    print while <$fh>;
    close $fh;
    alarm 0;
};
if($@) {
    die unless $@ eq "alarm \n";
}

Upvotes: 2

Related Questions