File Coverage

blib/lib/Parallel/Forker/Process.pm
Criterion Covered Total %
statement 181 277 65.3
branch 67 142 47.1
condition 22 56 39.2
subroutine 28 46 60.8
pod 21 26 80.7
total 319 547 58.3


line stmt bran cond sub pod time code
1             # See copyright, etc in below POD section.
2             ######################################################################
3              
4             package Parallel::Forker::Process;
5             require 5.006;
6 34     34   223 use Carp qw(carp croak confess);
  34         68  
  34         1780  
7 34     34   172 use IO::File;
  34         62  
  34         3966  
8 34     34   18871 use POSIX qw(sys_wait_h :signal_h);
  34         223503  
  34         185  
9 34     34   74804 use Proc::ProcessTable;
  34         169298  
  34         1627  
10 34     34   248 use Scalar::Util qw(weaken);
  34         41  
  34         1469  
11              
12 34     34   176 use strict;
  34         50  
  34         740  
13 34     34   141 use vars qw($Debug $VERSION $HashId);
  34         45  
  34         79413  
14              
15             $VERSION = '1.258';
16              
17             $Debug = $Parallel::Forker::Debug;
18             $HashId = 0;
19              
20             sub _new {
21 414     414   752 my $class = shift;
22             my $self = {
23             _forkref => undef, # Upper Fork object
24             name => $HashId++, # ID for hashing. User may override it
25             label => undef, # Label for run_after's
26             _after_children => {}, # IDs that are waiting on this event
27             _after_parents => {}, # IDs that we need to wait for
28             _state => 'idle', # 'idle', 'ready', 'runable', 'running', 'done', 'parerr'
29             _ref_count => 0, # number of people depending on us
30             pid => undef, # Pid # running as, undef=not running
31             run_after => [], # Process objects that are prereqs
32       223     run_pre_start => sub {},
33 0     0   0 run_on_start => sub {confess "%Error: No run_on_start defined\n";},
34 0     0   0 run_on_finish => sub {my ($procref,$status) = @_;}, # Routine taking child and exit status
35             @_
36 414         8435 };
37 414         1930 $Debug = $Parallel::Forker::Debug;
38 414   33     2411 bless $self, ref($class)||$class;
39             # Users need to delete the old one first, if they care.
40             # We don't do that automatically, as generally this is a mistake, and
41             # deleting the old one may terminate a process or have other nasty effects.
42             (!exists $self->{_forkref}{_processes}{$self->{name}})
43 414 50       1480 or croak "%Error: Creating a new process under the same name as an existing process: $self->{name},";
44 414         1275 $self->{_forkref}{_processes}{$self->{name}} = $self;
45 414         1553 weaken($self->{_forkref});
46              
47 414 100       921 if (defined $self->{label}) {
48 108 50       308 if (ref $self->{label}) {
49 0         0 foreach my $label (@{$self->{label}}) {
  0         0  
50 0         0 push @{$self->{_forkref}{_labels}{$label}}, $self;
  0         0  
51             }
52             } else {
53 108         172 push @{$self->{_forkref}{_labels}{$self->{label}}}, $self;
  108         414  
54             }
55             }
56 414         1174 $self->_calc_runable; # Recalculate
57 414         1111 return $self;
58             }
59              
60             sub DESTROY {
61 0     0   0 my $self = shift;
62 0         0 delete $self->{_forkref}{_processes}{$self->{name}};
63             }
64              
65             ##### ACCESSORS
66              
67 301     301 1 5804 sub name { return $_[0]->{name}; }
68 0     0 1 0 sub label { return $_[0]->{label}; }
69 0     0 1 0 sub pid { return $_[0]->{pid}; }
70 0     0 1 0 sub status { return $_[0]->{status}; } # Maybe undef
71 234   66 234 1 7220 sub status_ok { return defined $_[0]->{status} && $_[0]->{status}==0; }
72 0     0 1 0 sub forkref { return $_[0]->{_forkref}; }
73              
74 0     0 1 0 sub state { return $_[0]->{_state}; }
75 525     525 1 3828 sub is_idle { return $_[0]->{_state} eq 'idle'; }
76 525     525 1 2690 sub is_ready { return $_[0]->{_state} eq 'ready'; }
77 0     0 1 0 sub is_runable { return $_[0]->{_state} eq 'runable'; }
78 223     223 1 2459 sub is_running { return $_[0]->{_state} eq 'running'; }
79 1446     1446 1 30047 sub is_done { return $_[0]->{_state} eq 'done'; }
80 754     754 1 11004 sub is_parerr { return $_[0]->{_state} eq 'parerr'; }
81             sub is_reapable {
82 0     0 1 0 my $self = shift;
83 0   0     0 return $self->{_ref_count} == 0 && ($self->is_done || $self->is_parerr);
84             }
85              
86 394     394 0 1020 sub reference { $_[0]->{_ref_count}++ }
87 294     294 0 1639 sub unreference { $_[0]->{_ref_count}-- }
88              
89             ##### METHODS
90              
91             sub _calc_eqns {
92 414     414   591 my $self = shift;
93              
94             # Convert references to names of the reference
95             $self->{run_after} = [map
96             {
97 394 100       1061 if (ref $_) { $_ = $_->{name} };
  96         374  
98 394         1502 $_;
99 414         711 } @{$self->{run_after}} ];
  414         995  
100              
101 414         934 my $run_after = (join " & ", @{$self->{run_after}});
  414         1323  
102 414         3342 $run_after =~ s/([&\|\!\^\---\(\)])/ $1 /g;
103 414 50 50     1380 print " FrkRunafter $self->{name}: $run_after\n" if ($Debug||0)>=2;
104              
105 414         680 my $runable_eqn = "";
106 414         660 my $parerr_eqn = "";
107 414         565 my $ignerr;
108 414         857 my $flip_op = ''; # ~ or ^ or empty
109 414         658 my $between_op = '&&';
110 414         583 my $between_op_not = '||';
111 414         685 my $need_op_next = 0;
112 414         631 my $any_refs = 0;
113 414         3107 foreach my $token (split /\s+/, " $run_after ") {
114 980 100       3965 next if $token =~ /^\s*$/;
115             #print "TOKE $token\n" if $Debug;
116 657 100 100     5995 if ($token eq '!' || $token eq '^') {
    100 33        
    50          
    100          
    100          
    50          
117 64         258 $flip_op = $token;
118             } elsif ($token eq '-') {
119 32         138 $ignerr = 1;
120             } elsif ($token eq '(' || $token eq ')') {
121 0 0       0 if ($token eq '(') {
122 0 0       0 $runable_eqn .= " ${between_op}" if $need_op_next;
123 0 0       0 $parerr_eqn .= " ${between_op_not}" if $need_op_next;
124 0         0 $need_op_next = 0;
125             }
126 0         0 $runable_eqn .= " $token ";
127 0         0 $parerr_eqn.= " $token ";
128             } elsif ($token eq '&') {
129 71         174 $between_op = '&&'; $between_op_not = '||';
  71         156  
130             } elsif ($token eq '|') {
131 64         156 $between_op = '||'; $between_op_not = '&&';
  64         124  
132             } elsif ($token =~ /^[a-z0-9_]*$/i) {
133             # Find it
134 426         1908 my @found = $self->{_forkref}->find_proc_name($token);
135 426 100       1145 if (defined $found[0]) {
136 394         769 foreach my $aftref (@found) {
137 394         754 my $aftname = $aftref->{name};
138 394 50       1406 ($aftref ne $self) or die "%Error: Id $self->{name} has a run_after on itself; it will never start\n";
139 394 100       899 $runable_eqn .= " ${between_op}" if $need_op_next;
140 394 100       964 $parerr_eqn .= " ${between_op_not}" if $need_op_next;
141             # _ranok, _ranfail, _nofail
142 394 100       963 if ($flip_op eq '!') {
    100          
143 32         208 $runable_eqn .= " (_ranfail('$aftname')||_parerr('$aftname'))";
144 32         96 $parerr_eqn .= " (_ranok('$aftname'))";
145             } elsif ($flip_op eq '^') {
146 32         432 $runable_eqn .= " (_ranok('$aftname')||_ranfail('$aftname')||_parerr('$aftname'))";
147 32         60 $parerr_eqn .= " (0)";
148             } else {
149 330         884 $runable_eqn .= " (_ranok('$aftname'))";
150 330         889 $parerr_eqn .= " (_ranfail('$aftname')||_parerr('$aftname'))";
151             }
152              
153 394         1114 $aftref->{_after_children}{$self->{name}} = $self;
154 394         806 $self->{_after_parents}{$aftref->{name}} = $aftref;
155 394         1715 weaken($aftref->{_after_children}{$self->{name}});
156 394         1241 weaken($self->{_after_parents}{$aftref->{name}});
157              
158 394 100 50     798 my $apo = $flip_op; $apo ||= 'O' if $between_op eq '||';
  394         1502  
159 394 100 100     1601 $apo ||= '&'; $apo='E' if $apo eq '!';
  394         1061  
160 394         1261 $self->{_after_parents_op}{$aftref->{name}} = $apo;
161 394         673 $need_op_next = 1;
162 394         877 $any_refs = 1;
163             }
164             } else {
165 32 50       110 if ($ignerr) {
166 32 50       1776 print " FrkProc $self->{name} run_after process/label $token not found ignored.\n" if $Debug;
167             } else {
168 0         0 croak "%Error: run_after process/label $token not found,";
169             }
170             }
171             # Prep for next
172 426         806 $ignerr = 0;
173 426         1185 $flip_op = '';
174             } else {
175 0         0 croak "%Error: run_after parse error of $token in: $run_after,";
176             }
177             }
178 414 100       1259 $runable_eqn = "1" if !$any_refs;
179 414 100       963 $parerr_eqn = "0" if !$any_refs;
180 414         973 $self->{_runafter_text} = $run_after;
181 414         919 $self->{_runable_eqn_text} = $runable_eqn;
182 414         1140 $self->{_parerr_eqn_text} = $parerr_eqn;
183 414         1326 my $set = ("\t\$self->{_runable_eqn} = sub { return $runable_eqn; };\n"
184             ."\t\$self->{_parerr_eqn} = sub { return $parerr_eqn; };1;\n");
185 414 50 50     1410 print "$set" if ($Debug||0)>=2;
186 414 50       68744 eval $set or die ("%Error: Can't eval:\n$@\n"
187             ." $self->{_runafter_text}\n $self->{_runable_eqn_text}\n $self->{_parerr_eqn_text}\n");
188             }
189              
190             sub ready {
191 414     414 1 952 my $self = shift;
192             # User is indicating ready.
193 414 50       1145 ($self->{_state} eq 'idle') or croak "%Error: Signalling ready to already ready process,";
194              
195 414         1179 $self->_calc_eqns;
196              
197             # Transition: idle -> 'ready'
198 414 50       16463 print " FrkProc $self->{name} $self->{_state} -> ready\n" if $Debug;
199 414 50       2559 if (not $self->is_ready) {
200 414         692 $_->reference for values %{$self->{_after_parents}};
  414         2361  
201             }
202 414         1050 $self->{_state} = 'ready';
203 414         1063 $self->_calc_runable;
204             }
205              
206             sub parerr {
207 111     111 0 380 my $self = shift;
208             # Mark process as never to be run
209 111 50 33     453 if ($self->is_idle || $self->is_ready) {
210 111 50       5272 print " FrkProc $self->{name} $self->{_state} -> parerr\n" if $Debug;
211 111         636 $self->{_state} = 'parerr'; # "can't run due to parent status" is more accurate
212             } else {
213 0         0 croak "%Error: process isn't ready\n";
214             }
215             # May need to spawn/kill children
216 111         295 foreach my $ra (values %{$self->{_after_children}}) {
  111         830  
217 111         756 $ra->_calc_runable;
218             }
219             }
220              
221             sub run {
222 223     223 1 780 my $self = shift;
223             # Transition: Any state -> 'running', ignoring run_after's
224 223 50       737 !$self->{pid} or croak "%Error: process is already running,";
225 223 50       1744 !$self->is_running or croak "%Error: process is already running,";
226              
227 223 50       12059 print " FrkProc $self->{name} $self->{_state} -> running\n" if $Debug;
228 223         2523 $self->{_state} = 'running';
229 223         1783 $self->{start_time} = time();
230 223         2544 $self->{run_pre_start}->($self);
231 223 100       236986 if (my $pid = fork()) {
232 195         4287 $self->{pid} = $pid;
233 195         7137 $self->{pid_last_run} = $pid;
234 195         10709 $self->{_forkref}{_running}{$self->{pid}} = $self;
235 195         6000 delete $self->{_forkref}{_runable}{$self->{name}};
236             } else {
237 28         5437 $self->{run_on_start}->($self);
238 23         842839 exit(0); # Don't close anything
239             }
240 195         8389 return $self; # So can chain commands
241             }
242              
243             sub run_after {
244 0     0 1 0 my $self = shift;
245             # @_ = objects to add as prereqs
246 0 0       0 ($self->{_state} eq 'idle') or croak "%Error: Must set run_after's before marking the process ready,";
247 0         0 push @{$self->{run_after}}, @_;
  0         0  
248 0         0 return $self; # So can chain commands
249             }
250              
251             sub reap {
252 0     0 1 0 my $self = shift;
253              
254 0 0       0 $self->is_reapable or croak "%Error: process is not reapable,";
255 0         0 delete $self->{_forkref}{_processes}{$self->{name}};
256 0 0       0 if (defined $self->{label}) {
257 0 0       0 if (ref $self->{label}) {
258 0         0 foreach my $label (@{$self->{label}}) {
  0         0  
259 0         0 @{$self->{_forkref}{_labels}{$label}} =
260 0         0 grep { $_->{name} ne $self->{name} }
261 0         0 @{$self->{_forkref}{_labels}{$label}};
  0         0  
262             }
263             } else {
264 0         0 @{$self->{_forkref}{_labels}{$self->{label}}} =
265 0         0 grep { $_->{name} ne $self->{name} }
266 0         0 @{$self->{_forkref}{_labels}{$self->{label}}};
  0         0  
267             }
268             }
269             }
270              
271 34     34   272 use vars qw($_Calc_Runable_Fork);
  34         68  
  34         50461  
272              
273             sub _calc_runable {
274 1158     1158   2798 my $self = shift;
275             # @_ = objects to add as prereqs
276 1158 100       4543 return if ($self->{_state} ne 'ready');
277             #use Data::Dumper; print "CR ",Dumper($self),"\n";
278              
279             # Used by the callbacks
280 704         2223 local $_Calc_Runable_Fork = $self->{_forkref};
281             sub _ranok {
282 653     653   3177 my $procref = $_Calc_Runable_Fork->{_processes}{$_[0]};
283 653 50 50     2365 print " _ranok $procref->{name} State $procref->{_state}\n" if ($Debug||0)>=2;
284 653   100     2073 return ($procref->is_done && $procref->status_ok);
285             }
286             sub _ranfail {
287 604     604   1861 my $procref = $_Calc_Runable_Fork->{_processes}{$_[0]};
288 604 50 50     2462 print " _ranfail $procref->{name} State $procref->{_state}\n" if ($Debug||0)>=2;
289 604   100     1387 return ($procref->is_done && !$procref->status_ok);
290             }
291             sub _parerr {
292 565     565   2427 my $procref = $_Calc_Runable_Fork->{_processes}{$_[0]};
293 565 50 50     1796 print " _parerr $procref->{name} State $procref->{_state}\n" if ($Debug||0)>=2;
294 565         1666 return ($procref->is_parerr);
295             }
296              
297 704 100       1649 if (&{$self->{_runable_eqn}}) {
  704 100       28775  
298             # Transition: ready -> runable
299 258 50       7275 print " FrkProc $self->{name} $self->{_state} -> runable\n" if $Debug;
300 258         2581 $self->{_state} = 'runable'; # No dependencies (yet) so can launch it
301 258         2900 $self->{_forkref}{_runable}{$self->{name}} = $self;
302 446         8561 } elsif (&{$self->{_parerr_eqn}}) {
303 111         350 $_->unreference for values %{$self->{_after_parents}};
  111         757  
304 111         717 $self->parerr;
305             }
306             }
307              
308             ##### STATE TRANSITIONS
309              
310             our $_Warned_Waitpid;
311              
312             sub poll {
313 313     313 1 1105 my $self = shift;
314 313 50       1768 return undef if !$self->{pid};
315              
316 313         6476 my $got = waitpid($self->{pid}, WNOHANG);
317 313 100       1846 if ($got!=0) {
318 169 50       912 if ($got>0) {
319 169         3697 $self->{status} = $?; # convert wait return to status
320             } else {
321 0         0 $self->{status} = undef;
322 0 0 0     0 carp "%Warning: waitpid($self->{pid}) returned -1 instead of status; perhaps you're ignoring SIG{CHLD}?"
323             if ($^W && !$_Warned_Waitpid);
324 0         0 $_Warned_Waitpid = 1;
325             }
326             # Transition: running -> 'done'
327 169 50       13078 print " FrkProc $self->{name} $self->{_state} -> done ($self->{status})\n" if $Debug;
328 169         2323 delete $self->{_forkref}{_running}{$self->{pid}};
329 169         911 $self->{pid} = undef;
330 169         1974 $self->{_state} = 'done';
331 169         1962 $self->{end_time} = time();
332 169         2792 $self->{run_on_finish}->($self, $self->{status});
333             # Transition children: ready -> runable
334 169         2383 foreach my $ra (values %{$self->{_after_children}}) {
  169         3072  
335 219         1775 $ra->_calc_runable;
336             }
337 169         636 $_->unreference for values %{$self->{_after_parents}};
  169         2109  
338             # Done
339 169         1345 return $self;
340             }
341 144         1069 return undef;
342             }
343              
344             sub kill {
345 0     0 1   my $self = shift;
346 0   0       my $signal = shift || 9;
347 0 0         CORE::kill($signal, $self->{pid}) if $self->{pid};
348             # We don't remove it's pid, we'll get a child exit that will do it
349             }
350              
351             sub kill_tree {
352 0     0 1   my $self = shift;
353 0   0       my $signal = shift || 9;
354 0 0         return if !$self->{pid};
355 0           my @proc = (_subprocesses($self->{pid}), $self->{pid});
356 0           foreach my $pid (@proc) {
357 0 0         print " Fork Kill -$signal $pid (child of $pid)\n" if $Debug;
358 0           CORE::kill($signal, $pid);
359             }
360             # We don't remove it's pid, we'll get a child exit that will do it
361             }
362              
363             sub format_time {
364 0     0 0   my $secs = shift;
365 0           return sprintf("%02d:%02d:%02d", int($secs/3600), int(($secs%3600)/60), $secs % 60);
366             }
367              
368             sub format_loctime {
369 0     0 0   my $time = shift;
370 0           my ($sec,$min,$hour) = localtime($time);
371 0           return sprintf("%02d:%02d:%02d", $hour, $min, $sec);
372             }
373              
374             sub _write_tree_line {
375 0     0     my $self = shift;
376 0           my $level = shift;
377 0           my $linenum = shift;
378 0           my $cmt = "";
379 0 0         if (!$linenum) {
    0          
    0          
    0          
    0          
380 0           my $state = uc $self->{_state};
381 0 0 0       $state .= "-ok" if $self->is_done && $self->status_ok;
382 0 0 0       $state .= "-err" if $self->is_done && !$self->status_ok;
383             return sprintf("%s %-27s %-8s %s\n",
384             "--", #x$level
385             $self->{name},
386             $state, # DONE-err is longest
387 0   0       ($self->{comment}||""));
388             } elsif ($linenum == 1) {
389 0 0         if ($self->{start_time}) {
390 0           $cmt .= "Start ".format_loctime($self->{start_time});
391 0 0         if ($self->{end_time}) {
392 0           $cmt .= ", End ".format_loctime($self->{end_time});
393 0           $cmt .= ", Took ".format_time(($self->{end_time}-$self->{start_time}));
394 0           $cmt .= ", Pid ".$self->{pid_last_run};
395             }
396             }
397             } elsif ($linenum == 2) {
398 0 0         $cmt .= "Runaft = ".$self->{_runafter_text} if defined $self->{_runafter_text};
399             } elsif ($linenum == 3) {
400 0 0         $cmt .= "RunEqn = ".$self->{_runable_eqn_text} if defined $self->{_runable_eqn_text} ;
401             } elsif ($linenum == 4) {
402 0 0         $cmt .= "ErrEqn = ".$self->{_parerr_eqn_text} if defined $self->{_parerr_eqn_text} ;
403             }
404 0           return sprintf("%s %-27s %-8s %s\n",
405             " ", #x$level
406             "",
407             "",
408             $cmt);
409             }
410              
411             sub _subprocesses {
412 0   0 0     my $parent = shift || $$;
413             # All pids under the given parent
414             # Used by testing module
415             # Same function in Schedule::Load::_subprocesses
416 0           my $pt = new Proc::ProcessTable( 'cache_ttys' => 1);
417 0           my %parent_pids;
418 0           foreach my $p (@{$pt->table}) {
  0            
419 0           $parent_pids{$p->pid} = $p->ppid;
420             }
421 0           my @out;
422 0           my @search = ($parent);
423 0           while ($#search > -1) {
424 0           my $pid = shift @search;
425 0 0         push @out, $pid if $pid ne $parent;
426 0           foreach (keys %parent_pids) {
427 0 0         push @search, $_ if $parent_pids{$_} == $pid;
428             }
429             }
430 0           return @out;
431             }
432              
433             ######################################################################
434             #### Package return
435             1;
436             =pod
437              
438             =head1 NAME
439              
440             Parallel::Forker::Process - Single parallel fork process object
441              
442             =head1 SYNOPSIS
443              
444             $obj->run;
445             $obj->poll;
446             $obj->kill(<"SIGNAL">);
447             $obj->kill_tree(<"SIGNAL">);
448              
449             =head1 DESCRIPTION
450              
451             Manage a single process under the control of Parallel::Forker.
452              
453             Processes are created by calling a Parallel::Forker object's schedule
454             method, and retrieved by various methods in that class.
455              
456             Processes transition over 6 states. They begin in idle state, and are
457             transitioned by the user into ready state. As their dependencies complete,
458             Parallel::Forker transitions them to the runable state. As the
459             Parallel::Forker object's C limit permits, they transition to the
460             running state, and get executed. On completion, they transition to the
461             done state. If a process depends on another process, and that other
462             process fails, the dependant process transitions to the parerr (parent
463             error) state, and is never run.
464              
465             =head1 METHODS
466              
467             =over 4
468              
469             =item forkref
470              
471             Return the parent Parallel::Forker object this process belongs to.
472              
473             =item is_done
474              
475             Returns true if the process is in the done state.
476              
477             =item is_idle
478              
479             Returns true if the process is in the idle state.
480              
481             =item is_parerr
482              
483             Returns true if the process is in the parent error state.
484              
485             =item is_ready
486              
487             Returns true if the process is in the ready state.
488              
489             =item is_reapable
490              
491             Returns true if the process is reapable (->reap may be called on it).
492              
493             =item is_runable
494              
495             Returns true if the process is in the runable state.
496              
497             =item is_running
498              
499             Returns true if the process is in the running state.
500              
501             =item kill()
502              
503             Send the specified signal to the process if it is running. If no signal is
504             specified, send a SIGKILL (9).
505              
506             =item kill_tree()
507              
508             Send the specified signal to the process (and its subchildren) if it is
509             running. If no signal is specified, send a SIGKILL (9).
510              
511             =item kill_tree_all()
512              
513             Send a signal to this child (and its subchildren) if it is running. If no
514             signal is specified, send a SIGKILL (9).
515              
516             =item label
517              
518             Return the label of the process, if any, else undef.
519              
520             =item name
521              
522             Return the name of the process.
523              
524             =item pid
525              
526             Return the process ID if this job is running, else undef.
527              
528             =item poll
529              
530             Check the process for activity, invoking callbacks if needed.
531             Generally Parallel::Forker's object method C is used instead.
532              
533             =item ready
534              
535             Mark this process as being ready for execution when all C's are
536             ready and CPU resources permit. When that occurs, run will be called on
537             the process automatically.
538              
539             =item reap
540              
541             When the process has no other processes waiting for it, and the process is
542             is_done or is_parerr, remove the data structures for it. This reclaims
543             memory for when a large number of processes are being created, run, and
544             destroyed.
545              
546             =item run
547              
548             Unconditionally move the process to the "running" state and start it.
549              
550             =item run_after
551              
552             Add a new (or list of) processes that must be completed before this process
553             can be runnable. You may pass a process object (from schedule), a process
554             name, or a process label. You may use "|" or "&" in a string to run this
555             process after ANY processes exit, or after ALL exit (the default.)
556             ! in front of a process name indicates to run if that process fails with
557             bad exit status. ^ in front of a process indicates to run if that process
558             succeeds OR fails.
559              
560             =item state
561              
562             Returns the name of the current state, 'idle', 'ready', 'runable',
563             'running', 'done' or 'parerr'. For forward compatibility, use the is_idle
564             etc. methods instead of comparing this accessor's value to a constant
565             string.
566              
567             =item status
568              
569             Return the exit status of this process if it has completed. The exit
570             status will only be correct if a CHLD signal handler is installed,
571             otherwise it may be undef.
572              
573             =item status_ok
574              
575             Return true if the exit status of this process was zero. Return false if
576             not ok, or if the status has not been determined, or if the status was
577             undef.
578              
579             =back
580              
581             =head1 DISTRIBUTION
582              
583             The latest version is available from CPAN and from
584             L.
585              
586             Copyright 2002-2020 by Wilson Snyder. This package is free software; you
587             can redistribute it and/or modify it under the terms of either the GNU
588             Lesser General Public License Version 3 or the Perl Artistic License
589             Version 2.0.
590              
591             =head1 AUTHORS
592              
593             Wilson Snyder
594              
595             =head1 SEE ALSO
596              
597             L
598              
599             =cut
600             ######################################################################