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   205 use Carp qw(carp croak confess);
  34         67  
  34         1824  
7 34     34   180 use IO::File;
  34         93  
  34         3932  
8 34     34   19126 use POSIX qw(sys_wait_h :signal_h);
  34         232954  
  34         196  
9 34     34   76402 use Proc::ProcessTable;
  34         172577  
  34         1764  
10 34     34   246 use Scalar::Util qw(weaken);
  34         57  
  34         1606  
11              
12 34     34   193 use strict;
  34         46  
  34         867  
13 34     34   173 use vars qw($Debug $VERSION $HashId);
  34         67  
  34         79560  
14              
15             $VERSION = '1.260';
16              
17             $Debug = $Parallel::Forker::Debug;
18             $HashId = 0;
19              
20             sub _new {
21 414     414   818 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         9134 };
37 414         1867 $Debug = $Parallel::Forker::Debug;
38 414   33     1861 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       1324 or croak "%Error: Creating a new process under the same name as an existing process: $self->{name},";
44 414         1280 $self->{_forkref}{_processes}{$self->{name}} = $self;
45 414         1268 weaken($self->{_forkref});
46              
47 414 100       957 if (defined $self->{label}) {
48 108 50       290 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         140 push @{$self->{_forkref}{_labels}{$self->{label}}}, $self;
  108         376  
54             }
55             }
56 414         1181 $self->_calc_runable; # Recalculate
57 414         1037 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 302     302 1 6490 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 7758 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 3371 sub is_idle { return $_[0]->{_state} eq 'idle'; }
76 525     525 1 2717 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 2583 sub is_running { return $_[0]->{_state} eq 'running'; }
79 1446     1446 1 27519 sub is_done { return $_[0]->{_state} eq 'done'; }
80 754     754 1 11026 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 1047 sub reference { $_[0]->{_ref_count}++ }
87 295     295 0 1330 sub unreference { $_[0]->{_ref_count}-- }
88              
89             ##### METHODS
90              
91             sub _calc_eqns {
92 414     414   688 my $self = shift;
93              
94             # Convert references to names of the reference
95             $self->{run_after} = [map
96             {
97 394 100       1001 if (ref $_) { $_ = $_->{name} };
  96         220  
98 394         1370 $_;
99 414         811 } @{$self->{run_after}} ];
  414         1169  
100              
101 414         948 my $run_after = (join " & ", @{$self->{run_after}});
  414         1214  
102 414         3290 $run_after =~ s/([&\|\!\^\---\(\)])/ $1 /g;
103 414 50 50     1602 print " FrkRunafter $self->{name}: $run_after\n" if ($Debug||0)>=2;
104              
105 414         712 my $runable_eqn = "";
106 414         689 my $parerr_eqn = "";
107 414         557 my $ignerr;
108 414         679 my $flip_op = ''; # ~ or ^ or empty
109 414         624 my $between_op = '&&';
110 414         557 my $between_op_not = '||';
111 414         643 my $need_op_next = 0;
112 414         541 my $any_refs = 0;
113 414         2902 foreach my $token (split /\s+/, " $run_after ") {
114 980 100       4427 next if $token =~ /^\s*$/;
115             #print "TOKE $token\n" if $Debug;
116 657 100 100     5892 if ($token eq '!' || $token eq '^') {
    100 33        
    50          
    100          
    100          
    50          
117 64         170 $flip_op = $token;
118             } elsif ($token eq '-') {
119 32         78 $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         187 $between_op = '&&'; $between_op_not = '||';
  71         152  
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         1805 my @found = $self->{_forkref}->find_proc_name($token);
135 426 100       988 if (defined $found[0]) {
136 394         831 foreach my $aftref (@found) {
137 394         800 my $aftname = $aftref->{name};
138 394 50       1454 ($aftref ne $self) or die "%Error: Id $self->{name} has a run_after on itself; it will never start\n";
139 394 100       1124 $runable_eqn .= " ${between_op}" if $need_op_next;
140 394 100       803 $parerr_eqn .= " ${between_op_not}" if $need_op_next;
141             # _ranok, _ranfail, _nofail
142 394 100       1225 if ($flip_op eq '!') {
    100          
143 32         142 $runable_eqn .= " (_ranfail('$aftname')||_parerr('$aftname'))";
144 32         96 $parerr_eqn .= " (_ranok('$aftname'))";
145             } elsif ($flip_op eq '^') {
146 32         228 $runable_eqn .= " (_ranok('$aftname')||_ranfail('$aftname')||_parerr('$aftname'))";
147 32         150 $parerr_eqn .= " (0)";
148             } else {
149 330         1032 $runable_eqn .= " (_ranok('$aftname'))";
150 330         902 $parerr_eqn .= " (_ranfail('$aftname')||_parerr('$aftname'))";
151             }
152              
153 394         1011 $aftref->{_after_children}{$self->{name}} = $self;
154 394         895 $self->{_after_parents}{$aftref->{name}} = $aftref;
155 394         1917 weaken($aftref->{_after_children}{$self->{name}});
156 394         1328 weaken($self->{_after_parents}{$aftref->{name}});
157              
158 394 100 50     697 my $apo = $flip_op; $apo ||= 'O' if $between_op eq '||';
  394         1402  
159 394 100 100     1964 $apo ||= '&'; $apo='E' if $apo eq '!';
  394         860  
160 394         1313 $self->{_after_parents_op}{$aftref->{name}} = $apo;
161 394         669 $need_op_next = 1;
162 394         923 $any_refs = 1;
163             }
164             } else {
165 32 50       138 if ($ignerr) {
166 32 50       1564 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         788 $ignerr = 0;
173 426         1161 $flip_op = '';
174             } else {
175 0         0 croak "%Error: run_after parse error of $token in: $run_after,";
176             }
177             }
178 414 100       1452 $runable_eqn = "1" if !$any_refs;
179 414 100       891 $parerr_eqn = "0" if !$any_refs;
180 414         1235 $self->{_runafter_text} = $run_after;
181 414         684 $self->{_runable_eqn_text} = $runable_eqn;
182 414         1649 $self->{_parerr_eqn_text} = $parerr_eqn;
183 414         1718 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     1694 print "$set" if ($Debug||0)>=2;
186 414 50       68348 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 991 my $self = shift;
192             # User is indicating ready.
193 414 50       1184 ($self->{_state} eq 'idle') or croak "%Error: Signalling ready to already ready process,";
194              
195 414         1194 $self->_calc_eqns;
196              
197             # Transition: idle -> 'ready'
198 414 50       18995 print " FrkProc $self->{name} $self->{_state} -> ready\n" if $Debug;
199 414 50       2201 if (not $self->is_ready) {
200 414         703 $_->reference for values %{$self->{_after_parents}};
  414         2350  
201             }
202 414         1140 $self->{_state} = 'ready';
203 414         1161 $self->_calc_runable;
204             }
205              
206             sub parerr {
207 111     111 0 308 my $self = shift;
208             # Mark process as never to be run
209 111 50 33     680 if ($self->is_idle || $self->is_ready) {
210 111 50       5766 print " FrkProc $self->{name} $self->{_state} -> parerr\n" if $Debug;
211 111         994 $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         508 foreach my $ra (values %{$self->{_after_children}}) {
  111         1624  
217 111         730 $ra->_calc_runable;
218             }
219             }
220              
221             sub run {
222 223     223 1 868 my $self = shift;
223             # Transition: Any state -> 'running', ignoring run_after's
224 223 50       805 !$self->{pid} or croak "%Error: process is already running,";
225 223 50       1858 !$self->is_running or croak "%Error: process is already running,";
226              
227 223 50       8800 print " FrkProc $self->{name} $self->{_state} -> running\n" if $Debug;
228 223         2623 $self->{_state} = 'running';
229 223         1485 $self->{start_time} = time();
230 223         2589 $self->{run_pre_start}->($self);
231 223 100       224482 if (my $pid = fork()) {
232 195         3899 $self->{pid} = $pid;
233 195         6789 $self->{pid_last_run} = $pid;
234 195         11117 $self->{_forkref}{_running}{$self->{pid}} = $self;
235 195         4792 delete $self->{_forkref}{_runable}{$self->{name}};
236             } else {
237 28         5434 $self->{run_on_start}->($self);
238 23         828678 exit(0); # Don't close anything
239             }
240 195         10144 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   302 use vars qw($_Calc_Runable_Fork);
  34         87  
  34         51508  
272              
273             sub _calc_runable {
274 1159     1159   2457 my $self = shift;
275             # @_ = objects to add as prereqs
276 1159 100       5112 return if ($self->{_state} ne 'ready');
277             #use Data::Dumper; print "CR ",Dumper($self),"\n";
278              
279             # Used by the callbacks
280 704         3326 local $_Calc_Runable_Fork = $self->{_forkref};
281             sub _ranok {
282 653     653   2533 my $procref = $_Calc_Runable_Fork->{_processes}{$_[0]};
283 653 50 50     3003 print " _ranok $procref->{name} State $procref->{_state}\n" if ($Debug||0)>=2;
284 653   100     2384 return ($procref->is_done && $procref->status_ok);
285             }
286             sub _ranfail {
287 604     604   2076 my $procref = $_Calc_Runable_Fork->{_processes}{$_[0]};
288 604 50 50     2834 print " _ranfail $procref->{name} State $procref->{_state}\n" if ($Debug||0)>=2;
289 604   100     1764 return ($procref->is_done && !$procref->status_ok);
290             }
291             sub _parerr {
292 565     565   2325 my $procref = $_Calc_Runable_Fork->{_processes}{$_[0]};
293 565 50 50     2109 print " _parerr $procref->{name} State $procref->{_state}\n" if ($Debug||0)>=2;
294 565         1376 return ($procref->is_parerr);
295             }
296              
297 704 100       1397 if (&{$self->{_runable_eqn}}) {
  704 100       32573  
298             # Transition: ready -> runable
299 258 50       7972 print " FrkProc $self->{name} $self->{_state} -> runable\n" if $Debug;
300 258         2582 $self->{_state} = 'runable'; # No dependencies (yet) so can launch it
301 258         3758 $self->{_forkref}{_runable}{$self->{name}} = $self;
302 446         8247 } elsif (&{$self->{_parerr_eqn}}) {
303 111         444 $_->unreference for values %{$self->{_after_parents}};
  111         1533  
304 111         1320 $self->parerr;
305             }
306             }
307              
308             ##### STATE TRANSITIONS
309              
310             our $_Warned_Waitpid;
311              
312             sub poll {
313 314     314 1 934 my $self = shift;
314 314 50       1650 return undef if !$self->{pid};
315              
316 314         7334 my $got = waitpid($self->{pid}, WNOHANG);
317 314 100       1708 if ($got!=0) {
318 169 50       1520 if ($got>0) {
319 169         4591 $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       13624 print " FrkProc $self->{name} $self->{_state} -> done ($self->{status})\n" if $Debug;
328 169         2278 delete $self->{_forkref}{_running}{$self->{pid}};
329 169         747 $self->{pid} = undef;
330 169         2431 $self->{_state} = 'done';
331 169         1893 $self->{end_time} = time();
332 169         2484 $self->{run_on_finish}->($self, $self->{status});
333             # Transition children: ready -> runable
334 169         1649 foreach my $ra (values %{$self->{_after_children}}) {
  169         2615  
335 220         1602 $ra->_calc_runable;
336             }
337 169         809 $_->unreference for values %{$self->{_after_parents}};
  169         2335  
338             # Done
339 169         1528 return $self;
340             }
341 145         1328 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             ######################################################################