Win32::Job - Run sub-processes in a "job" environment |
Win32::Job - Run sub-processes in a ``job'' environment
use Win32::Job; my $job = Win32::Job->new;
# Run 'perl Makefile.PL' for 10 seconds $job->spawn($Config{perlpath}, "perl Makefile.PL"); $job->run(10);
Win32::Job requires Windows 2000 or later. Windows 95, 98, NT, and Me are not supported.
Windows 2000 introduced the concept of a ``job'': a collection of processes which can be controlled as a single unit. For example, you can reliably kill a process and all of its children by launching the process in a job, then telling Windows to kill all processes in the job. Win32::Job makes this feature available to Perl.
For example, imagine you want to allow 2 minutes for a process to complete. If you have control over the child process, you can probably just run it in the background, then poll every second to see if it has finished.
That's fine as long as the child process doesn't spawn any child processes. What if it does? If you wrote the child process yourself and made an effort to clean up your child processes before terminating, you don't have to worry. If not, you will leave hanging processes (called ``zombie'' processes in Unix).
With Win32::Job, just create a new Job, then use the job to spawn the child
process. All its children will also be created in the new Job. When you
time out, just call the job's kill()
method and the entire process tree will
be terminated.
The following methods are available:
new()
new();
Creates a new Job object using the Win32 API call CreateJobObject(). The job is created with a default security context, and is unnamed.
Note: this method returns undef
if CreateJobObject()
fails. Look at $^E
for more detailed error information.
spawn()
spawn($exe, $args, \%opts);
Creates a new process and associates it with the Job. The process is initially suspended, and can be resumed with one of the other methods. Uses the Win32 API call CreateProcess(). Returns the PID of the newly created process.
Note: this method returns undef
if CreateProcess()
fails. See $^E
for
more detailed error information. One reason this will fail is if the calling
process is itself part of a job, and the job's security context does not allow
child processes to be created in a different job context than the parent.
The arguments are described here:
The executable program to run. This may be undef
, in which case the first
argument in $args is the program to run.
If this has path information in it, it is used ``as is'' and passed to CreateProcess(), which interprets it as either an absolute path, or a path relative to the current drive and directory. If you did not specify an extension, ``.exe'' is assumed.
If there are no path separators (either backslashes or forward slashes), then Win32::Job will search the current directory and your PATH, looking for the file. In addition, if you did not specify an extension, then Win32::Job checks ``.exe'', ``.com'', and ``.bat'' in order. If it finds a ``.bat'' file, Win32::Job will actually call cmd.exe and prepend ``cmd.exe'' to the $args.
For example, assuming a fairly normal PATH:
spawn(q{c:\winnt\system\cmd.exe}, q{cmd /C "echo %PATH%"}) exefile: c:\winnt\system\cmd.exe cmdline: cmd /C "echo %PATH%"
spawn("cmd.exe", q{cmd /C "echo %PATH%"}) exefile: c:\winnt\system\cmd.exe cmdline: cmd /C "echo %PATH%"$args
The commandline to pass to the executable program. The first word will be
argv[0]
to an EXE file, so you should repeat the command name in $args.
For example:
$job->spawn($Config{perlpath}, "perl foo.pl");
In this case, the ``perl'' is ignored, since perl.exe doesn't use it.
%optsA hash reference for advanced options. This parameter is optional. the following keys are recognized:
By default, the process shares the parent's current directory, .
.
By default, the process shares the parent's console. This has no effect on GUI programs which do not interact with the console.
minimized
, which displays the new window minimized; maximimzed
,
which shows the new window maximized; or hidden
, which does not display the
new window.
By default, the window is displayed using its application's defaults.
By default, the process is in the parent's process group (but in a new job).
window_attr
tag instead.
By default, the process shares its parent's console.
By default, the child process shares the parent's standard input.
By default, the child process shares the parent's standard output.
By default, the child process shares the parent's standard error.
Unrecognized keys are ignored.
run()
run($timeout, $which);
Provides a simple way to run the programs with a time limit. The $timeout is in seconds with millisecond accuracy. This call blocks for up to $timeout seconds, or until the processes finish.
The $which parameter specifies whether to wait for all processes to
complete within the $timeout, or whether to wait for any process to
complete. You should set this to a boolean, where a true value means to
wait for all the processes to complete, and a false value to wait
for any. If you do not specify $which, it defaults to true (all
).
Returns a boolean indicating whether the processes exited by themselves, or whether the time expired. A true return value means the processes exited normally; a false value means one or more processes was killed will $timeout.
You can get extended information on process exit codes using the
status()
method.
For example, this is how to build two perl modules at the same time, with a 5 minute timeout:
use Win32::Job; $job = Win32::Job->new; $job->spawn("cmd", q{cmd /C "cd Mod1 && nmake"}); $job->spawn("cmd", q{cmd /C "cd Mod2 && nmake"}); $ok = $job->run(5 * 60); print "Mod1 and Mod2 built ok!\n" if $ok;
watch()
watch(\&handler, $interval, $which);
handler($job);
Provides more fine-grained control over how to stop the programs. You specify a callback and an interval in seconds, and Win32::Job will call the ``watchdog'' function at this interval, either until the processes finish or your watchdog tells Win32::Job to stop. You must return a value indicating whether to stop: a true value means to terminate the processes immediately.
The $which parameter has the same meaning as run()'s.
Returns a boolean with the same meaning as run()'s.
The handler may do anything it wants. One useful application of the watch()
method is to check the filesize of the output file, and terminate the Job if
the file becomes larger than a certain limit:
use Win32::Job; $job = Win32::Job->new; $job->spawn("cmd", q{cmd /C "cd Mod1 && nmake"}, { stdin => 'NUL', # the NUL device stdout => 'stdout.log', stderr => 'stdout.log', }); $ok = $job->watch(sub { return 1 if -s "stdout.log" > 1_000_000; }, 1); print "Mod1 built ok!\n" if $ok;
status()
status()
Returns a hash containing information about the processes in the job.
Only returns valid information after calling either run()
or watch();
returns an empty hash if you have not yet called them. May be called from a
watch()
callback, in which case the exitcode
field should be ignored.
The keys of the hash are the process IDs; the values are a subhash containing the following keys:
user
, the amount of time the process spent in user
space; (ii) kernel
, the amount of time the process spent in kernel space;
and (iii) elapsed
, the total time the process was running.
kill()
kill();
Kills all processes and subprocesses in the Job. Has no return value.
Sets the exit code to all processes killed to 293, which you can check
for in the status()
return value.
For more information about jobs, see Microsoft's online help at
http://msdn.microsoft.com/
For other modules which do similar things (but not as well), see:
Low-level access to creating processes in Win32. See the Win32::Process manpage.
Win32::ConsoleLow-level access to consoles in Win32. See the Win32::Console manpage.
Win32::ProcFarmManage pools of threads to perform CPU-intensive tasks on Windows. See the Win32::ProcFarm manpage.
ActiveState (support@ActiveState.com)
Copyright (c) 2002, ActiveState Corporation. All Rights Reserved.
Win32::Job - Run sub-processes in a "job" environment |