use Time::HiRes qw( time ); use IO::Select qw( ); ... my $buf = ''; if (!eval { my $pid = open(my $fh, '-|', @cmd) or die("Can't create child: $!\n"); my $deadline = time() + 5; my $sel = IO::Select->new($fh); for (;;) { my $time_left = $deadline - time; die("Timeout\n") if $time_left <= 0; next if !$sel->can_read($time_left); my $rv = sysread($fh, $buf, 64*1024, length($buf); die("Can't read from child: $!\n") if !defined($rv); last if !$rv; } waitpid($pid, 0); die("Can't waitpid: $!\n") if $? == -1; die("Child killed by signal ".($? & 0x7F)."\n") if $? & 0x7F; die("Child returned error ".($? >> 8)."\n") if $? >> 8; 1 }) { my $e = $@; kill(TERM => $pid); waitpid($pid, 0); die($e); } ...