3 package PerlACE
::Process
;
6 use POSIX
"sys_wait_h";
12 ###############################################################################
14 ###############################################################################
20 if (defined $Config{sig_name
}) {
22 foreach my $name (split (' ', $Config{sig_name
})) {
29 for ($i = 0; $i < 255; ++$i) {
34 ###############################################################################
36 ### Constructor and Destructor
41 my $class = ref ($proto) || $proto;
45 $self->{IGNOREEXESUBDIR
} = 0;
46 $self->{PROCESS
} = undef;
47 $self->{EXECUTABLE
} = shift;
48 $self->{ARGUMENTS
} = shift;
49 $self->{VALGRIND_CMD
} = $ENV{'ACE_RUN_VALGRIND_CMD'};
51 if (!defined $PerlACE::Process
::WAIT_DELAY_FACTOR
) {
52 if (defined $self->{PURIFY_CMD
}) {
53 $PerlACE::Process
::WAIT_DELAY_FACTOR
= 10;
55 elsif (defined $self->{VALGRIND_CMD
}) {
56 $PerlACE::Process
::WAIT_DELAY_FACTOR
= 5;
59 $PerlACE::Process
::WAIT_DELAY_FACTOR
= 1;
63 bless ($self, $class);
71 if ($self->{RUNNING
} == 1) {
72 print STDERR
"ERROR: <", $self->{EXECUTABLE
},
73 "> still running upon object destruction\n";
78 ###############################################################################
87 $self->{EXECUTABLE
} = shift;
90 my $executable = $self->{EXECUTABLE
};
92 if ($self->{IGNOREEXESUBDIR
}) {
96 my $basename = basename
($executable);
97 my $dirname = dirname
($executable). '/';
99 $executable = $dirname.$PerlACE::Process
::ExeSubDir
.$basename;
102 $executable = $dirname.$basename;
105 if ( !-x
$executable ) {
106 if ( -x
$executable.'.exe' ) {
107 $executable = $executable.'.exe';
119 $self->{ARGUMENTS
} = shift;
122 return $self->{ARGUMENTS
};
129 my $commandline = $self->Executable ();
131 if (defined $self->{ARGUMENTS
}) {
132 $commandline .= ' '.$self->{ARGUMENTS
};
143 $self->{IGNOREEXESUBDIR
} = shift;
146 return $self->{IGNOREEXESUBDIR
};
154 $self->{IGNOREHOSTROOT
} = shift;
157 return $self->{IGNOREHOSTROOT
};
160 ###############################################################################
162 # Spawn the process and continue;
168 if ($self->{RUNNING
} == 1) {
169 print STDERR
"ERROR: Cannot Spawn: <", $self->Executable (),
170 "> already running\n";
174 if (!defined $self->{EXECUTABLE
}) {
175 print STDERR
"ERROR: Cannot Spawn: No executable specified\n";
179 if ($self->{IGNOREEXESUBDIR
} == 0) {
180 if (!-f
$self->Executable ()) {
181 print STDERR
"ERROR: Cannot Spawn: <", $self->Executable (),
186 if (!-x
$self->Executable ()) {
187 print STDERR
"ERROR: Cannot Spawn: <", $self->Executable (),
188 "> not executable\n";
193 $self->{PROCESS
} = VmsProcess
::Spawn
$self->{EXECUTABLE
}, $self->{ARGUMENTS
};
194 if ($self->{PROCESS
}) {
200 print STDERR
"ERROR: Can't spawn <" . $self->CommandLine () . ">: $!\n";
202 $self->{RUNNING
} = 1;
206 # The second argument is an optional output argument that, if present,
207 # will be passed to check_return_value function to get the signal number
208 # the process has received, if any, and/or whether there was a core dump.
215 my $status = $self->TimedWait ($timeout, $opts);
218 print STDERR
"ERROR: $self->{EXECUTABLE} timedout\n";
222 $self->{RUNNING
} = 0;
228 # Do a Spawn and immediately WaitKill
230 sub SpawnWaitKill
($)
235 if ($self->Spawn () == -1) {
239 return $self->WaitKill ($timeout);
242 sub TerminateWaitKill
($)
247 if ($self->{RUNNING
}) {
248 print STDERR
"INFO: $self->{EXECUTABLE} being killed.\n";
249 kill ('TERM', $self->{PROCESS
});
252 return $self->WaitKill ($timeout);
255 # Really only for internal use.
256 # The second optional argument indicates whether the corresponding process
257 # may deliberately send a signal to itself or not. It also contains output
258 # data indicating whether there was a core dump and/or the signal nubmer
259 # the process has died from, if any.
260 sub check_return_value
($)
264 my $opts = shift // {};
269 elsif ($rc == 0xff00) {
270 print STDERR
"ERROR: <", $self->{EXECUTABLE
},
274 elsif (($rc & 0xff) == 0) {
285 my $self_crash = $opts->{self_crash
};
287 # ABRT, KILL or TERM can be sent deliberately
288 if ($self_crash && ($rc == 6 || $rc == 9 || $rc == 15)) {
292 my $signal_ref = $opts->{signal_ref
};
293 if (defined $signal_ref) {
294 ${$signal_ref} = $rc;
297 my $dump_ref = $opts->{dump_ref
};
298 if (defined $dump_ref) {
299 ${$dump_ref} = $dump;
302 print STDERR
"ERROR: <", $self->{EXECUTABLE
},
305 print STDERR
"coredump from " if ($dump == 1);
307 print STDERR
"signal $rc : ", $signame[$rc], "\n";
316 if ($self->{RUNNING
}) {
317 kill ('KILL', $self->{PROCESS
});
318 waitpid ($self->{PROCESS
}, 0);
319 $self->check_return_value ($?
, {self_crash
=> 1});
322 $self->{RUNNING
} = 0;
325 # Wait until a process exits.
326 # return -1 if the process is still alive.
331 if (!defined $timeout || $timeout < 0) {
332 waitpid ($self->{PROCESS
}, 0);
334 return TimedWait
($self, $timeout);
339 # The second argument is an optional output argument that, if present,
340 # will contain the signal number that the process has received, if any,
341 # and/or whether there was a core dump.
348 $timeout *= $PerlACE::Process
::WAIT_DELAY_FACTOR
;
351 my $pid = VmsProcess
::TimedWaitPid
($self->{PROCESS
}, $timeout, $status);
353 return $self->check_return_value ($status, $opts);
362 my $procmask = shift;
364 ## NOT IMPLEMENTED YET