use strict; use IPC::Open3; use IO::Select; use Symbol; sub _run_ReadWrite { my ($invocant, $cmd, $input) = @_; # Declare needed variables my ($child_pid, $output, $errors, $select, $fh, @ready); my ($child_in, $child_out, $child_err) = (gensym, gensym, gensym); # Try to connect to specified process eval { $child_pid = open3($child_in, $child_out, $child_err, $cmd) }; # ..... throw error if $@ ..... # Feed input to process, then close input print $child_in $input; close ($child_in); # Create a select object and add fhs $select = IO::Select->new(); $select->add($child_out, $child_err); # This loop will block until data is available while ( @ready = $select->can_read ) { # We now have a list of readable fhs foreach $fh ( @ready ) { # Read 4096 bytes of data my $data; my $len = sysread $fh, $data, 4096; # There was a read error if ( !defined $len ) { # ..... throw error ..... } # Current filehandle is empty, remove from select object elsif ( $len == 0 ) { $select->remove($fh) and next } # Data was read from a proper fh, add it to proper var elsif ( $fh == $child_out ) { $output .= $data and next } elsif ( $fh == $child_err ) { $errors .= $data and next } # There was an unexpected error else { # ..... throw error ..... } } } # Process can be reaped waitpid($child_pid, 0); # Return collected results return { OUTPUT => $output , ERRORS => $errors }; }