|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
  
 
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Proc::Background::Unix;  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $Proc::Background::Unix::VERSION = '1.32';  | 
| 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # ABSTRACT: Unix-specific implementation of process create/wait/kill  | 
| 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 require 5.004_04;  | 
| 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
6
 | 
22
 | 
 
 | 
 
 | 
  
22
  
 | 
 
 | 
139
 | 
 use strict;  | 
| 
 
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
57
 | 
    | 
| 
 
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
626
 | 
    | 
| 
7
 | 
22
 | 
 
 | 
 
 | 
  
22
  
 | 
 
 | 
511
 | 
 use Exporter;  | 
| 
 
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
64
 | 
    | 
| 
 
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
757
 | 
    | 
| 
8
 | 
22
 | 
 
 | 
 
 | 
  
22
  
 | 
 
 | 
136
 | 
 use Carp;  | 
| 
 
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
43
 | 
    | 
| 
 
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1058
 | 
    | 
| 
9
 | 
22
 | 
 
 | 
 
 | 
  
22
  
 | 
 
 | 
11048
 | 
 use POSIX qw( :errno_h :sys_wait_h );  | 
| 
 
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
181582
 | 
    | 
| 
 
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
92
 | 
    | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Test for existence of FD_CLOEXEC, needed for child-error-through-pipe trick  | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my ($FD_CLOEXEC);  | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 eval {  | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   require Fcntl;  | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $FD_CLOEXEC= Fcntl::FD_CLOEXEC();  | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 };  | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # For un-explained mysterious reasons, Time::HiRes::alarm seem to misbehave on 5.10 and earlier  | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # but core alarm works fine.  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $alarm= ($] >= 5.012)? do { require Time::HiRes; \&Time::HiRes::alarm; }  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   : sub {  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # round up to whole seconds  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 		CORE::alarm(POSIX::ceil($_[0]));  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 	};  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 @Proc::Background::Unix::ISA = qw(Exporter);  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Start the background process.  If it is started sucessfully, then record  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # the process id in $self->{_os_obj}.  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _start {  | 
| 
31
 | 
108
 | 
 
 | 
 
 | 
  
108
  
 | 
 
 | 
479
 | 
   my ($self, $options)= @_;  | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # There are three main scenarios for how-to-exec:  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #   * single-string command, to be handled by shell  | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #   * arrayref command, to be handled by execve  | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #   * arrayref command with 'exe' (fake argv0)  | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # and one that isn't logical:  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   #   * single-string command with exe  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # throw an error for that last one rather than trying something awkward  | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # like splitting the command string.  | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
42
 | 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
276
 | 
   my @argv;  | 
| 
43
 | 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
311
 | 
   my ($cmd, $exe)= @{$self}{'_command','_exe'};  | 
| 
 
 | 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
565
 | 
    | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
45
 | 
108
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
657
 | 
   if (ref $cmd eq 'ARRAY') {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
46
 | 
103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
455
 | 
     @argv= @$cmd;  | 
| 
47
 | 
103
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
996
 | 
     ($exe, my $err) = Proc::Background::_resolve_path(defined $exe? $exe : $argv[0]);  | 
| 
48
 | 
103
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
944
 | 
     return $self->_fatal($err) unless defined $exe;  | 
| 
49
 | 
101
 | 
 
 | 
 
 | 
 
 | 
 
 | 
681
 | 
     $self->{_exe}= $exe;  | 
| 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif (defined $exe) {  | 
| 
51
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     croak "Can't combine 'exe' option with single-string 'command', use arrayref 'command' instead.";  | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
54
 | 
106
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
652
 | 
   if (defined $options->{cwd}) {  | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     -d $options->{cwd}  | 
| 
56
 | 
7
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
107
 | 
       or return $self->_fatal("directory does not exist: '$options->{cwd}'");  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
59
 | 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
322
 | 
   my ($new_stdin, $new_stdout, $new_stderr);  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $new_stdin= _resolve_file_handle($options->{stdin}, '<', \*STDIN)  | 
| 
61
 | 
104
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
461
 | 
     if exists $options->{stdin};  | 
| 
62
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $new_stdout= _resolve_file_handle($options->{stdout}, '>>', \*STDOUT)  | 
| 
63
 | 
104
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
605
 | 
     if exists $options->{stdout};  | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   $new_stderr= _resolve_file_handle($options->{stderr}, '>>', \*STDERR)  | 
| 
65
 | 
104
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
605
 | 
     if exists $options->{stderr};  | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # Fork a child process.  | 
| 
68
 | 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
313
 | 
   my ($pipe_r, $pipe_w);  | 
| 
69
 | 
104
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
476
 | 
   if (defined $FD_CLOEXEC) {  | 
| 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # use a pipe for the child to report exec() errors  | 
| 
71
 | 
104
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
7339
 | 
     pipe $pipe_r, $pipe_w or return $self->_fatal("pipe: $!");  | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # This pipe needs to be in the non-preserved range that doesn't exist after exec().  | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # In the edge case where a pipe received a FD less than $^F, the CLOEXEC flag isn't set.  | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Try again on higher descriptors, then close the lower ones.  | 
| 
75
 | 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
476
 | 
     my @rejects;  | 
| 
76
 | 
104
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
1934
 | 
     while (fileno $pipe_r <= $^F or fileno $pipe_w <= $^F) {  | 
| 
77
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       push @rejects, $pipe_r, $pipe_w;  | 
| 
78
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       pipe $pipe_r, $pipe_w or return $self->_fatal("pipe: $!");  | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
81
 | 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
319
 | 
   my $pid;  | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   {  | 
| 
83
 | 
104
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
200
 | 
     if ($pid = fork()) {  | 
| 
 
 | 
104
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
106423
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       # parent  | 
| 
85
 | 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3920
 | 
       $self->{_os_obj} = $pid;  | 
| 
86
 | 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1912
 | 
       $self->{_pid}    = $pid;  | 
| 
87
 | 
87
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
1310
 | 
       if (defined $pipe_r) {  | 
| 
88
 | 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4026
 | 
         close $pipe_w;  | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # wait for child to reply or close the pipe  | 
| 
90
 | 
87
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
14429
 | 
         local $SIG{PIPE}= sub {};  | 
| 
91
 | 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1009
 | 
         my $msg= '';  | 
| 
92
 | 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30701605
 | 
         while (0 < read $pipe_r, $msg, 1024, length $msg) {}  | 
| 
93
 | 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3769
 | 
         close $pipe_r;  | 
| 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # If child wrote anything to the pipe, it failed to exec.  | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # Reap it before dying.  | 
| 
96
 | 
87
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4299
 | 
         if (length $msg) {  | 
| 
97
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
           waitpid $pid, 0;  | 
| 
98
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
           return $self->_fatal($msg);  | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
101
 | 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
499
 | 
       last;  | 
| 
102
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif (defined $pid) {  | 
| 
103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       # child  | 
| 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       # Make absolutely sure nothing in this block interacts with the rest of the  | 
| 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       # process state, and that flow control never skips the _exit().  | 
| 
106
 | 
17
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
5372
 | 
       $SIG{$_}= sub{die;} for qw( INT HUP QUIT TERM ); # clear custom signal handlers  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
107
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1718
 | 
       $SIG{$_}= 'DEFAULT' for qw( __WARN__ __DIE__ );  | 
| 
108
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
594
 | 
       eval {  | 
| 
109
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
334
 | 
         eval {  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
           chdir($options->{cwd}) or die "chdir($options->{cwd}): $!\n"  | 
| 
111
 | 
17
 | 
  
100
  
 | 
  
 50
  
 | 
 
 | 
 
 | 
1369
 | 
             if defined $options->{cwd};  | 
| 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
113
 | 
17
 | 
  
100
  
 | 
  
 50
  
 | 
 
 | 
 
 | 
1226
 | 
           open STDIN, '<&'.fileno($new_stdin) or die "Can't redirect STDIN: $!\n"  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             if defined $new_stdin;  | 
| 
115
 | 
17
 | 
  
100
  
 | 
  
 50
  
 | 
 
 | 
 
 | 
1176
 | 
           open STDOUT, '>&'.fileno($new_stdout) or die "Can't redirect STDOUT: $!\n"  | 
| 
116
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             if defined $new_stdout;  | 
| 
117
 | 
17
 | 
  
100
  
 | 
  
 50
  
 | 
 
 | 
 
 | 
538
 | 
           open STDERR, '>&'.fileno($new_stderr) or die "Can't redirect STDERR: $!\n"  | 
| 
118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             if defined $new_stderr;  | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
120
 | 
17
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
369
 | 
           if (defined $exe) {  | 
| 
121
 | 
16
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
108
 | 
             exec { $exe } @argv or die "$0: exec failed: $!\n";  | 
| 
 
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
122
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
           } else {  | 
| 
123
 | 
1
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             exec $cmd or die "$0: exec failed: $!\n";  | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
           }  | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         };  | 
| 
126
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         if (defined $pipe_w) {  | 
| 
127
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
           print $pipe_w $@;  | 
| 
128
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
           close $pipe_w; # force it to flush.  Nothing else needs closed because we are about to _exit  | 
| 
129
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
130
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
           print STDERR $@;  | 
| 
131
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       };  | 
| 
133
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       POSIX::_exit(1);  | 
| 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif ($! == EAGAIN) {  | 
| 
135
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       sleep 5;  | 
| 
136
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       redo;  | 
| 
137
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
138
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       return $self->_fatal("fork: $!");  | 
| 
139
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
142
 | 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7564
 | 
   $self;  | 
| 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
145
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _resolve_file_handle {  | 
| 
146
 | 
32
 | 
 
 | 
 
 | 
  
32
  
 | 
 
 | 
221
 | 
   my ($thing, $mode, $default)= @_;  | 
| 
147
 | 
32
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
169
 | 
   if (!defined $thing) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
148
 | 
11
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
743
 | 
     open my $fh, $mode, '/dev/null' or croak "open(/dev/null): $!";  | 
| 
149
 | 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
114
 | 
     return $fh;  | 
| 
150
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } elsif (ref $thing) {  | 
| 
151
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # use 'undef' to mean no-change  | 
| 
152
 | 
19
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
98
 | 
     return (fileno($thing) == fileno($default))? undef : $thing;  | 
| 
153
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   } else {  | 
| 
154
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
196
 | 
     open my $fh, $mode, $thing or croak "open($thing): $!";  | 
| 
155
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
172
 | 
     return $fh;  | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
157
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
158
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # Wait for the child.  | 
| 
160
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   (0, exit_value)	: sucessfully waited on.  | 
| 
161
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   (1, undef)	: process already reaped and exit value lost.  | 
| 
162
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #   (2, undef)	: process still running.  | 
| 
163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _waitpid {  | 
| 
164
 | 
204
 | 
 
 | 
 
 | 
  
204
  
 | 
 
 | 
961
 | 
   my ($self, $blocking, $wait_seconds) = @_;  | 
| 
165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
166
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   {  | 
| 
167
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Try to wait on the process.  | 
| 
168
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Implement the optional timeout with the 'alarm' call.  | 
| 
169
 | 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
572
 | 
     my $result= 0;  | 
| 
 
 | 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
527
 | 
    | 
| 
170
 | 
204
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
1664
 | 
     if ($blocking && $wait_seconds) {  | 
| 
171
 | 
57
 | 
 
 | 
 
 | 
  
14
  
 | 
 
 | 
2796
 | 
       local $SIG{ALRM}= sub { die "alarm\n" };  | 
| 
 
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
671
 | 
    | 
| 
172
 | 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1236
 | 
       $alarm->($wait_seconds);  | 
| 
173
 | 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
800
 | 
       eval { $result= waitpid($self->{_os_obj}, 0); };  | 
| 
 
 | 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14566561
 | 
    | 
| 
174
 | 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2387
 | 
       $alarm->(0);  | 
| 
175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
176
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     else {  | 
| 
177
 | 
147
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
22115063
 | 
       $result= waitpid($self->{_os_obj}, $blocking? 0 : WNOHANG);  | 
| 
178
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Process finished.  Grab the exit value.  | 
| 
181
 | 
204
 | 
  
100
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
2547
 | 
     if ($result == $self->{_os_obj}) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
182
 | 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
356
 | 
       delete $self->{_suspended};  | 
| 
183
 | 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2834
 | 
       return (0, $?);  | 
| 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
185
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Process already reaped.  We don't know the exist status.  | 
| 
186
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     elsif ($result == -1 and $! == ECHILD) {  | 
| 
187
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       return (1, 0);  | 
| 
188
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
189
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Process still running.  | 
| 
190
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     elsif ($result == 0) {  | 
| 
191
 | 
117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
972
 | 
       return (2, 0);  | 
| 
192
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
193
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # If we reach here, then waitpid caught a signal, so let's retry it.  | 
| 
194
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     redo;  | 
| 
195
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
196
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
   return 0;  | 
| 
197
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
199
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _suspend {  | 
| 
200
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
   kill STOP => $_[0]->{_os_obj};  | 
| 
201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
202
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _resume {  | 
| 
204
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
   kill CONT => $_[0]->{_os_obj};  | 
| 
205
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
206
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
207
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _terminate {  | 
| 
208
 | 
26
 | 
 
 | 
 
 | 
  
26
  
 | 
 
 | 
183
 | 
   my $self = shift;  | 
| 
209
 | 
26
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
1288
 | 
   my @kill_sequence= @_ && ref $_[0] eq 'ARRAY'? @{ $_[0] } : qw( TERM 2 TERM 8 KILL 3 KILL 7 );  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
210
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # Try to kill the process with different signals.  Calling alive() will  | 
| 
211
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # collect the exit status of the program.  | 
| 
212
 | 
26
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
1371
 | 
   while (@kill_sequence and $self->alive) {  | 
| 
213
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
275
 | 
     my $sig= shift @kill_sequence;  | 
| 
214
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
125
 | 
     my $delay= shift @kill_sequence;  | 
| 
215
 | 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2045
 | 
     kill($sig, $self->{_os_obj});  | 
| 
216
 | 
26
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
247
 | 
     next unless defined $delay;  | 
| 
217
 | 
26
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
315
 | 
     last if $self->_reap(1, $delay); # block before sending next signal  | 
| 
218
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
220
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
221
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
222
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |