This is a bit simpler than yours, a lot simpler than the CPAN 'solutions', and it works even if the program produces a lot of output:
#! perl -slw
use strict;
use IPC::Open3;
use threads stack_size => 4096;
## Kill 0,pid does appear to work properly,
## It return true even after the executable is dead & gone
sub checkPid{
scalar( `tasklist /nh /fi "pid eq $_[0]"` !~ m[INFO]sm );
}
sub execute {
my( $timeout, @command, ) = @_;
my( $err, $in, $out ) = do{ local *FH; \*FH };
my $pid = open3( $in, $out, $err, @command )
or die "@command : $!/$@/$^E";
my( $Tout ) = threads->create( sub{
my( $Terr ) = threads->create( sub{ my @in = <$err>; return \@
+in } );
my @in = <$out>;
return \@in, $Terr->join;
} );
sleep 1 while checkPid( $pid ) and --$timeout;
kill 3, $pid unless $timeout;
return $Tout->join, $timeout == 0;
}
my @cmd = (
'perl.exe',
q[-le"$|++; print($_), warn( $_), Win32::Sleep 250 for 1 .. 12" ]
);
my( $out, $err, $timeout ) = execute( 2, @cmd );
print 'Command ', $timeout ? 'timed out' : 'completed';
print "From stdout:[\n @$out ]" if @$out;
print "From stderr:[\n @$err ]\n" if @$err;
( $out, $err, $timeout ) = execute( 5, @cmd );
print 'Command ', $timeout ? 'timed out' : 'completed';
print "From stdout:[\n @$out ]" if @$out;
print "From stderr:[\n @$err ]" if @$err;
Produces:
C:\test>869942
Command timed out
From stdout:[
1
2
3
4
5
]
From stderr:[
1 at -e line 1.
2 at -e line 1.
3 at -e line 1.
4 at -e line 1.
5 at -e line 1.
]
Command completed
From stdout:[
1
2
3
4
5
6
7
8
9
10
11
12
]
From stderr:[
1 at -e line 1.
2 at -e line 1.
3 at -e line 1.
4 at -e line 1.
5 at -e line 1.
6 at -e line 1.
7 at -e line 1.
8 at -e line 1.
9 at -e line 1.
10 at -e line 1.
11 at -e line 1.
12 at -e line 1.
]
The discrepancy between the 1 1/4 seconds of output gathered and the 2 second timeout in the first run, is down to pipe buffering.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.