2

I am trying to catch a timeout exception with IPC::Run on Windows 10 (using Strawberry Perl version 5.30.1):

use strict;
use warnings;
use feature qw(say);
use Data::Dumper;
use IPC::Run qw(run timeout);

my $timeout = 3;
my $cmd = ['perl', '-E', "sleep 5; say 'stdout_text'; say STDERR 'stderr_text'"];
my $in;
my $out;
my $err;
my $result;
eval {
    $result = run $cmd, \$in, \$out, \$err, timeout($timeout );
};
if ( $@ ) {
    say "Timed out: $@";
}
else {
    print Dumper({  out => $out, err => $err});
}

The above program dies after 3 seconds with:

Terminating on signal SIGBREAK(21)

How can I catch the timeout exception in the Perl script?

See also this issue.

Håkon Hægland
  • 39,012
  • 21
  • 81
  • 174
  • 1
    Did you try to handle the signal? Perhaps like [here](https://stackoverflow.com/a/53771631/4653379) – zdim Jan 26 '21 at 00:11
  • @zdim Thanks for link, yes it seems to work with a `$SIG{BREAK}` handler installed! – Håkon Hægland Jan 26 '21 at 00:18
  • Just got around to try it -- and I don't get a SIGBREAK, but an actual exception (handled by `eval` as usual). This is on Windows 10 (in a VM) with Strawberry Perl v5.30.2; the `IPC::Run` source shows `$VERSION` of `20200505.0`. (I'm confused?) – zdim Jan 26 '21 at 04:06

1 Answers1

0

Thanks to @zdim! You need to install a signal handler for the BREAK signal. The following works:

use strict;
use warnings;
use feature qw(say);
use Data::Dumper;
use IPC::Run qw(run timeout);

my $timeout = 3;
my $cmd = ['perl', '-E', "sleep 4; say 'stdout_text'; say STDERR 'stderr_text'"];
my $in;
my $out;
my $err;
my $result;
{
    local $SIG{BREAK} = sub { die "Got timeout signal" };
    eval {
        $result = run $cmd, \$in, \$out, \$err, timeout($timeout );
    };
}
if ( $@ ) {
    say "Timed out: $@";
}
else {
    print Dumper({  out => $out, err => $err});
} 

Output:

> perl p.pl
Timed out: Got timeout signal at p.pl line 14.
Håkon Hægland
  • 39,012
  • 21
  • 81
  • 174