File Coverage

blib/lib/Log/Saftpresse/Input/Command/Child.pm
Criterion Covered Total %
statement 6 57 10.5
branch 0 26 0.0
condition n/a
subroutine 2 7 28.5
pod 0 2 0.0
total 8 92 8.7


line stmt bran cond sub pod time code
1             package Log::Saftpresse::Input::Command::Child;
2              
3 1     1   4 use Moose;
  1         2  
  1         5  
4              
5             # ABSTRACT: process control for child processes of Command input
6             our $VERSION = '1.6'; # VERSION
7              
8 1     1   4723 use IO::File;
  1         2  
  1         757  
9              
10             has 'pid' => ( is => 'rw', isa => 'Maybe[Int]' );
11              
12             has 'stdout' => ( is => 'rw' );
13             has 'stderr' => ( is => 'rw' );
14              
15             has 'command' => ( is => 'ro', isa => 'Str', required => 1 );
16              
17             has 'blocking' => ( is => 'ro', isa => 'Bool', default => 1 );
18              
19             sub _setup_pipe {
20 0     0     my $reader = IO::File->new;
21 0           my $writer = IO::File->new;
22 0 0         pipe( $reader, $writer)
23             or die "failed creating pipe: $!";
24 0           return $reader, $writer;
25             }
26              
27             sub start {
28 0     0 0   my ( $self ) = @_;
29 0 0         if( $self->pid ) {
30 0           die "child is already running";
31             }
32              
33 0           my ( $parent_out, $child_out) = _setup_pipe;
34 0           my ( $parent_err, $child_err) = _setup_pipe;
35 0           my $pid;
36              
37             eval {
38 0           $pid = fork(); 1;
  0            
39 0 0         } or do {
40 0 0         my $error = $@ ne '' ? $@ : "errno=$!";
41 0           die "error forking child: $error";
42             };
43 0 0         defined $pid or die "cant fork child command: $!";
44 0 0         if( ! $pid ) {
45             # child
46 0           eval {
47 0           alarm(0);
48 0           $parent_out->close;
49 0           $parent_err->close;
50              
51 0 0         open( STDIN, '<', '/dev/null' )
52             or die "cant reopen STDOUT of child: $!";
53 0 0         open( STDOUT, '>&', $child_out )
54             or die "cant reopen STDOUT of child: $!";
55 0 0         open( STDERR, '>&', $child_err )
56             or die "cant reopen STDERR of child: $!";
57              
58 0           my $cmd = $self->command;
59 0 0         exec $cmd or die "cant exec $cmd: $!";
60             };
61 0           exit 1;
62             }
63             # parent
64 0           $child_out->close();
65 0           $child_err->close();
66 0           $self->pid( $pid );
67 0           $parent_out->blocking( $self->blocking );
68 0           $parent_err->blocking( $self->blocking );
69 0           $self->stdout( $parent_out );
70 0           $self->stderr( $parent_err );
71              
72 0           return;
73             }
74              
75             sub _is_pid_alive {
76 0     0     my $self = shift;
77 0           return kill(0, $self->pid);
78             }
79              
80             sub stop {
81 0     0 0   my $self = shift;
82              
83 0 0         if( ! defined $self->pid ) {
84 0           return;
85             }
86              
87 0 0         if( $self->_is_pid_alive ) {
88 0           kill( 'TERM', $self->pid);
89 0           waitpid( $self->pid, 0 );
90             }
91              
92 0 0         if( $self->pid ) {
93 0           $self->pid( undef );
94 0           $self->stdout->close;
95 0           $self->stderr->close;
96             }
97              
98 0           return;
99             }
100              
101             sub DESTROY {
102 0     0     my $self = shift;
103 0           $self->stop;
104 0           return;
105             }
106              
107             1;
108              
109             __END__
110              
111             =pod
112              
113             =encoding UTF-8
114              
115             =head1 NAME
116              
117             Log::Saftpresse::Input::Command::Child - process control for child processes of Command input
118              
119             =head1 VERSION
120              
121             version 1.6
122              
123             =head1 AUTHOR
124              
125             Markus Benning <ich@markusbenning.de>
126              
127             =head1 COPYRIGHT AND LICENSE
128              
129             This software is Copyright (c) 1998 by James S. Seymour, 2015 by Markus Benning.
130              
131             This is free software, licensed under:
132              
133             The GNU General Public License, Version 2, June 1991
134              
135             =cut