line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package System::Command::Reaper; |
2
|
|
|
|
|
|
|
$System::Command::Reaper::VERSION = '1.120'; |
3
|
39
|
|
|
39
|
|
270
|
use strict; |
|
39
|
|
|
|
|
80
|
|
|
39
|
|
|
|
|
1209
|
|
4
|
39
|
|
|
39
|
|
259
|
use warnings; |
|
39
|
|
|
|
|
76
|
|
|
39
|
|
|
|
|
863
|
|
5
|
39
|
|
|
39
|
|
686
|
use 5.006; |
|
39
|
|
|
|
|
150
|
|
6
|
|
|
|
|
|
|
|
7
|
39
|
|
|
39
|
|
236
|
use Carp; |
|
39
|
|
|
|
|
67
|
|
|
39
|
|
|
|
|
2133
|
|
8
|
39
|
|
|
39
|
|
220
|
use Scalar::Util qw( weaken reftype ); |
|
39
|
|
|
|
|
73
|
|
|
39
|
|
|
|
|
2513
|
|
9
|
|
|
|
|
|
|
|
10
|
39
|
|
|
39
|
|
20888
|
use POSIX ":sys_wait_h"; |
|
39
|
|
|
|
|
258157
|
|
|
39
|
|
|
|
|
194
|
|
11
|
|
|
|
|
|
|
|
12
|
39
|
|
|
39
|
|
62688
|
use constant MSWin32 => $^O eq 'MSWin32'; |
|
39
|
|
|
|
|
99
|
|
|
39
|
|
|
|
|
4557
|
|
13
|
39
|
|
|
39
|
|
274
|
use constant HANDLES => qw( stdin stdout stderr ); |
|
39
|
|
|
|
|
59
|
|
|
39
|
|
|
|
|
2722
|
|
14
|
39
|
|
|
39
|
|
221
|
use constant STATUS => qw( exit signal core ); |
|
39
|
|
|
|
|
100
|
|
|
39
|
|
|
|
|
3056
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
for my $attr ( HANDLES ) { |
17
|
39
|
|
|
39
|
|
272
|
no strict 'refs'; |
|
39
|
|
|
|
|
86
|
|
|
39
|
|
|
|
|
3673
|
|
18
|
0
|
|
|
0
|
|
0
|
*$attr = sub { return $_[0]{$attr} }; |
19
|
|
|
|
|
|
|
} |
20
|
|
|
|
|
|
|
for my $attr ( STATUS ) { |
21
|
39
|
|
|
39
|
|
267
|
no strict 'refs'; |
|
39
|
|
|
|
|
79
|
|
|
39
|
|
|
|
|
35516
|
|
22
|
0
|
|
|
0
|
|
0
|
*$attr = sub { $_[0]->is_terminated(); return $_[0]{$attr} }; |
|
0
|
|
|
|
|
0
|
|
23
|
|
|
|
|
|
|
} |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub new { |
26
|
99
|
|
|
99
|
1
|
860
|
my ($class, $command, $o) = @_; |
27
|
99
|
|
50
|
|
|
808
|
$o ||= {}; |
28
|
99
|
|
|
|
|
2894
|
my $self = bless { %$o, command => $command }, $class; |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
# copy/weaken the important keys |
31
|
99
|
|
|
|
|
644
|
@{$self}{ pid => HANDLES } = @{$command}{ pid => HANDLES }; |
|
99
|
|
|
|
|
1087
|
|
|
99
|
|
|
|
|
1602
|
|
32
|
99
|
|
|
|
|
3430
|
weaken $self->{$_} for ( command => HANDLES ); |
33
|
|
|
|
|
|
|
|
34
|
99
|
|
|
|
|
1795
|
return $self; |
35
|
|
|
|
|
|
|
} |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# this is necessary, because kill(0,pid) is misimplemented in perl core |
38
|
|
|
|
|
|
|
my $_is_alive = MSWin32 |
39
|
|
|
|
|
|
|
? sub { return `tasklist /FO CSV /NH /fi "PID eq $_[0]"` =~ /^"/ } |
40
|
|
|
|
|
|
|
: sub { return kill 0, $_[0]; }; |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub is_terminated { |
43
|
333
|
|
|
333
|
1
|
1026
|
my ($self) = @_; |
44
|
333
|
|
|
|
|
819
|
my $pid = $self->{pid}; |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# Zed's dead, baby. Zed's dead. |
47
|
333
|
100
|
100
|
|
|
1908
|
return $pid if !$_is_alive->($pid) and exists $self->{exit}; |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# If that is a re-animated body, we're gonna have to kill it. |
50
|
67
|
|
|
|
|
710
|
return $self->_reap(WNOHANG); |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub _reap { |
54
|
166
|
|
|
166
|
|
669
|
my ( $self, $flags ) = @_; |
55
|
|
|
|
|
|
|
|
56
|
166
|
100
|
|
|
|
766
|
$flags = 0 if ! defined $flags; |
57
|
|
|
|
|
|
|
|
58
|
166
|
|
|
|
|
561
|
my $pid = $self->{pid}; |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
# REPENT/THE END IS/EXTREMELY/FUCKING/NIGH |
61
|
166
|
100
|
100
|
|
|
4030812
|
if ( !exists $self->{exit} and my $reaped = waitpid( $pid, $flags ) ) { |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
# Well, it's a puzzle because, technically, you're not alive. |
64
|
99
|
|
|
|
|
929
|
my $zed = $reaped == $pid; |
65
|
99
|
100
|
66
|
|
|
3399
|
carp "Child process already reaped, check for a SIGCHLD handler" |
|
|
|
100
|
|
|
|
|
66
|
|
|
|
|
|
|
if !$zed && !$System::Command::QUIET && !MSWin32; |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
# What do you think? "Zombie Kill of the Week"? |
69
|
99
|
100
|
|
|
|
7829
|
@{$self}{ STATUS() } |
|
99
|
|
|
|
|
2200
|
|
70
|
|
|
|
|
|
|
= $zed |
71
|
|
|
|
|
|
|
? ( $? >> 8, $? & 127, $? & 128 ) |
72
|
|
|
|
|
|
|
: ( -1, -1, -1 ); |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
# Who died and made you fucking king of the zombies? |
75
|
99
|
100
|
|
|
|
887
|
if ( defined( my $cmd = $self->{command} ) ) { |
76
|
69
|
|
|
|
|
246
|
@{$cmd}{ STATUS() } = @{$self}{ STATUS() }; |
|
69
|
|
|
|
|
442
|
|
|
69
|
|
|
|
|
258
|
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# I know you're here, because I can smell your brains. |
79
|
69
|
|
|
|
|
314
|
my $o = $cmd->{options}; |
80
|
|
|
|
|
|
|
defined reftype( $o->{$_} ) |
81
|
|
|
|
|
|
|
and reftype( $o->{$_} ) eq 'SCALAR' |
82
|
21
|
|
|
|
|
606
|
and ${ $o->{$_} } = $self->{$_} |
83
|
69
|
|
66
|
|
|
2316
|
for STATUS(); |
|
|
|
66
|
|
|
|
|
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
# I think it's safe to assume it isn't a zombie. |
87
|
0
|
|
|
|
|
0
|
print { $self->{th} } "System::Command xit[$pid]: ", |
88
|
|
|
|
|
|
|
join( ', ', map "$_: $self->{$_}", STATUS() ), "\n" |
89
|
99
|
50
|
|
|
|
479
|
if $self->{trace}; |
90
|
|
|
|
|
|
|
|
91
|
99
|
|
|
|
|
611
|
return $reaped; # It's dead, Jim! |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
# Look! It's moving. It's alive. It's alive... |
95
|
67
|
|
|
|
|
538
|
return; |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
sub close { |
99
|
99
|
|
|
99
|
1
|
463
|
my ($self) = @_; |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# close all pipes |
102
|
99
|
|
|
|
|
376
|
my ( $in, $out, $err ) = @{$self}{qw( stdin stdout stderr )}; |
|
99
|
|
|
|
|
559
|
|
103
|
99
|
100
|
33
|
|
|
2063
|
$in and $in->opened and $in->close || carp "error closing stdin: $!"; |
|
|
|
100
|
|
|
|
|
104
|
99
|
100
|
33
|
|
|
5311
|
$out and $out->opened and $out->close || carp "error closing stdout: $!"; |
|
|
|
100
|
|
|
|
|
105
|
99
|
100
|
33
|
|
|
3197
|
$err and $err->opened and $err->close || carp "error closing stderr: $!"; |
|
|
|
100
|
|
|
|
|
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# and wait for the child (if any) |
108
|
99
|
|
|
|
|
2807
|
$self->_reap(); |
109
|
|
|
|
|
|
|
|
110
|
99
|
|
|
|
|
1780
|
return $self; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub DESTROY { |
114
|
97
|
|
|
97
|
|
239788
|
my ($self) = @_; |
115
|
97
|
|
|
|
|
605
|
local $?; |
116
|
97
|
|
|
|
|
684
|
local $!; |
117
|
97
|
100
|
|
|
|
1403
|
$self->close if !exists $self->{exit}; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
1; |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
__END__ |