File Coverage

lib/Rex/Interface/Exec/IOReader.pm
Criterion Covered Total %
statement 42 59 71.1
branch 22 38 57.8
condition 1 2 50.0
subroutine 4 4 100.0
pod 0 1 0.0
total 69 104 66.3


line stmt bran cond sub pod time code
1             #
2             # (c) Jan Gehring
3             #
4              
5             package Rex::Interface::Exec::IOReader;
6              
7 58     58   976 use v5.12.5;
  58         261  
8 58     58   397 use warnings;
  58         144  
  58         2731  
9              
10             our $VERSION = '1.14.3'; # VERSION
11              
12 58     58   490 use IO::Select;
  58         2000  
  58         30418  
13              
14             sub io_read {
15 2     2 0 102 my ( $self, $out_fh, $err_fh, $pid, $option ) = @_;
16 2         19 my ( $out, $err, $out_line, $err_line );
17              
18 2         56 my $selector = IO::Select->new();
19 2         74 $selector->add($out_fh);
20 2         217 $selector->add($err_fh);
21              
22 2   50     101 my $rex_int_conf = Rex::Commands::get("rex_internals") || {};
23 2         11 my $buffer_size = 1024;
24 2 50       23 if ( exists $rex_int_conf->{read_buffer_size} ) {
25 0         0 $buffer_size = $rex_int_conf->{read_buffer_size};
26             }
27              
28 2         19 my ( $last_line_stdout, $last_line_stderr ) = ( "", "" );
29              
30 2         20 while ( my @ready = $selector->can_read ) {
31 13702         557389 foreach my $fh (@ready) {
32 13944         19473 my $buf = "";
33              
34 13944         103684 my $len = sysread $fh, $buf, $buffer_size;
35 13944 100       34762 $selector->remove($fh) unless $len;
36              
37 13944         25809 $buf =~ s/\r?\n/\n/g; # normalize EOL characters
38              
39             # append buffer to the proper overall output
40 13944 100       27870 $out .= $buf if $fh == $out_fh;
41 13944 100       33102 $err .= $buf if $fh == $err_fh;
42              
43 13944 100       26728 if ( $buf =~ /\n/ ) { # buffer has one or more newlines
44 1         8 my @line_chunks = split /\n/, $buf;
45              
46 1         6 my $partial_last_chunk = '';
47 1 50       9 if ( $buf !~ /\n$/ ) { # last chunk is partial
48 0         0 $partial_last_chunk = pop @line_chunks;
49             }
50              
51 1         3 foreach my $chunk (@line_chunks) {
52 1 50       15 if ( $fh == $out_fh ) {
    50          
53 0         0 $out_line .= $chunk;
54             $self->execute_line_based_operation( $out_line, $option )
55 0 0       0 && do { kill( 'KILL', $pid ); goto END_OPEN };
  0         0  
  0         0  
56 0         0 $out_line = '';
57             }
58             elsif ( $fh == $err_fh ) {
59 1         3 $err_line .= $chunk;
60             $self->execute_line_based_operation( $err_line, $option )
61 1 50       13 && do { kill( 'KILL', $pid ); goto END_OPEN };
  0         0  
  0         0  
62 1         3 $err_line = '';
63             }
64             }
65              
66 1 50       8 if ($partial_last_chunk) { # append partial chunk to line if present
67 0 0       0 $out_line .= $partial_last_chunk if $fh == $out_fh;
68 0 0       0 $err_line .= $partial_last_chunk if $fh == $err_fh;
69             }
70              
71             }
72             else { # buffer doesn't have any newlines
73 13943 100       25001 $out_line .= $buf if $fh == $out_fh;
74 13943 100       51804 $err_line .= $buf if $fh == $err_fh;
75             }
76             }
77             }
78              
79 2 100       31 unless ($out) {
80 1         4 $out = $last_line_stdout;
81             $self->execute_line_based_operation( $out, $option )
82 1 50       5 && do { kill( 'KILL', $pid ); goto END_OPEN };
  0         0  
  0         0  
83             }
84              
85 2 50       15 unless ($err) {
86 0         0 $err = $last_line_stderr;
87             $self->execute_line_based_operation( $err, $option )
88 0 0       0 && do { kill( 'KILL', $pid ); goto END_OPEN };
  0         0  
  0         0  
89             }
90              
91             END_OPEN:
92              
93 2         627 return ( $out, $err );
94             }
95              
96             1;