File Coverage

lib/IOMux/IPC.pm
Criterion Covered Total %
statement 56 63 88.8
branch 13 30 43.3
condition 1 4 25.0
subroutine 11 14 78.5
pod 4 5 80.0
total 85 116 73.2


line stmt bran cond sub pod time code
1             # Copyrights 2011-2020 by [Mark Overmeer ].
2             # For other contributors see ChangeLog.
3             # See the manual pages for details on the licensing terms.
4             # Pod stripped from pm file by OODoc 2.02.
5             # This code is part of distribution IOMux. Meta-POD processed with OODoc
6             # into POD and HTML manual-pages. See README.md
7             # Copyright Mark Overmeer. Licensed under the same terms as Perl itself.
8              
9             package IOMux::IPC;
10 3     3   3243 use vars '$VERSION';
  3         3  
  3         127  
11             $VERSION = '1.01';
12              
13 3     3   12 use base 'IOMux::Bundle';
  3         6  
  3         638  
14              
15 3     3   15 use warnings;
  3         3  
  3         55  
16 3     3   12 use strict;
  3         3  
  3         46  
17              
18 3     3   12 use Log::Report 'iomux';
  3         3  
  3         10  
19              
20 3     3   1158 use IOMux::Pipe::Read ();
  3         6  
  3         48  
21 3     3   568 use IOMux::Pipe::Write ();
  3         7  
  3         66  
22              
23 3     3   14 use POSIX qw/:errno_h :sys_wait_h/;
  3         4  
  3         10  
24 3     3   863 use File::Basename 'basename';
  3         3  
  3         1430  
25              
26              
27             sub init($)
28 2     2 0 4 { my ($self, $args) = @_;
29             my $command = $args->{command}
30 2 50       6 or error __x"no command to run specified in {pkg}", pkg => __PACKAGE__;
31              
32 2 50       10 my ($cmd, @cmdopts) = ref $command eq 'ARRAY' ? @$command : $command;
33 2         96 my $name = $args->{name} = '|'.(basename $cmd).'|';
34              
35 2   50     12 my $mode = $args->{mode} || '|-|';
36 2         4 my $errors = $args->{errors};
37 2 50 0     8 if($mode eq '|=|') { $errors //= 1 }
  0 50       0  
38 2 50       6 elsif($mode eq '|-|') { $mode = '|=|' if $errors }
39             else
40 0         0 { error __x"unknown mode {mode} for {pkg}"
41             , mode => $mode, pkg => __PACKAGE__;
42             }
43              
44 2         6 ($args->{stdin}, my $in_rh)
45             = IOMux::Pipe::Write->bare(name => 'stdin');
46 2         10 ($args->{stdout}, my $out_wh)
47             = IOMux::Pipe::Read->bare(name => 'stdout');
48 2 50       4 ($args->{stderr}, my $err_wh)
49             = $errors ? IOMux::Pipe::Read->bare(name => 'stderr') : ();
50              
51 2         2004 my $pid = fork;
52 2 50       114 defined $pid
53             or fault __x"failed to fork for ipc {cmd}", cmd => $name;
54              
55 2 100       53 if($pid==0)
56             { # client
57 1 50       112 open STDIN, '<&', $in_rh
58             or fault __x"failed to redirect STDIN for ipc {cmd}", cmd=>$name;
59 1 50       36 open STDOUT, '>&', $out_wh
60             or fault __x"failed to redirect STDOUT for ipc {cmd}", cmd=>$name;
61 1 50       18 if($err_wh)
62 0 0       0 { open STDERR, '>&', $err_wh
63             or fault __x"failed to redirect STDERR for ipc {cmd}"
64             , cmd => $name;
65             }
66             else
67 1         136 { open STDERR, '>', File::Spec->devnull;
68             }
69              
70 1 0       0 exec $cmd, @cmdopts
71             or fault __x"failed to exec for pipe {cmd}", cmd => $name;
72             }
73              
74             # parent
75              
76 1         30 close $in_rh;
77 1         22 close $out_wh;
78 1 50       12 close $err_wh if $err_wh;
79              
80 1         70 $self->{IMI_pid} = $pid;
81 1         84 $self->SUPER::init($args);
82 1         46 $self;
83             }
84              
85              
86             sub open($$@)
87 0     0 1 0 { my ($class, $mode, $cmd) = (shift, shift, shift);
88 0 0       0 ref $cmd eq 'ARRAY'
89             ? $class->new(command => $cmd, mode => $mode, @_)
90             : $class->new(command => [$cmd, @_] , mode => $mode);
91             }
92              
93             #-------------------
94              
95 0     0 1 0 sub mode() {shift->{IMI_mode}}
96 0     0 1 0 sub childPid() {shift->{IMI_pid}}
97              
98             #-------------------
99              
100             sub close($)
101 1     1 1 784 { my ($self, $cb) = @_;
102 1         21 waitpid $self->{IMI_pid}, WNOHANG;
103 1         9 local $?;
104 1         9 $self->SUPER::close($cb);
105             }
106              
107             1;