home *** CD-ROM | disk | FTP | other *** search
- package Win32::Job;
-
- use strict;
- use base qw(DynaLoader);
- use vars qw($VERSION);
-
- $VERSION = '0.01';
-
- use constant WIN32s => 0;
- use constant WIN9X => 1;
- use constant WINNT => 2;
-
- my @ver = Win32::GetOSVersion;
- die "Win32::Job is not supported on $ver[0]" unless (
- $ver[4] == WINNT and (
- $ver[1] > 5 or
- ($ver[1] == 5 and $ver[2] > 0) or
- ($ver[1] == 5 and $ver[2] == 0 and $ver[3] >= 0)
- )
- );
-
- Win32::Job->bootstrap($VERSION);
-
- 1;
-
- __END__
-
- =head1 NAME
-
- Win32::Job - Run sub-processes in a "job" environment
-
- =head1 SYNOPSIS
-
- 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);
-
- =head1 PLATFORMS
-
- Win32::Job requires Windows 2000 or later. Windows 95, 98, NT, and Me are not
- supported.
-
- =head1 DESCRIPTION
-
- 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 I<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.
-
- =head1 Using Win32::Job
-
- The following methods are available:
-
- =over 4
-
- =item 1
-
- 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 C<undef> if CreateJobObject() fails. Look at C<$^E>
- for more detailed error information.
-
- =item 2
-
- 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 C<undef> if CreateProcess() fails. See C<$^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:
-
- =over 4
-
- =item 1
-
- $exe
-
- The executable program to run. This may be C<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 F<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%"
-
- =item 2
-
- $args
-
- The commandline to pass to the executable program. The first word will be
- C<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.
-
- =item 3
-
- %opts
-
- A hash reference for advanced options. This parameter is optional.
- the following keys are recognized:
-
- =over 4
-
- =item cwd
-
- A string specifying the current directory of the new process.
-
- By default, the process shares the parent's current directory, C<.>.
-
- =item new_console
-
- A boolean; if true, the process is started in a new console window.
-
- By default, the process shares the parent's console. This has no effect on GUI
- programs which do not interact with the console.
-
- =item window_attr
-
- Either C<minimized>, which displays the new window minimized; C<maximimzed>,
- which shows the new window maximized; or C<hidden>, which does not display the
- new window.
-
- By default, the window is displayed using its application's defaults.
-
- =item new_group
-
- A boolean; if true, the process is the root of a new process group. This
- process group includes all descendents of the child.
-
- By default, the process is in the parent's process group (but in a new job).
-
- =item no_window
-
- A boolean; if true, the process is run without a console window. This flag is
- only valid when starting a console application, otherwise it is ignored. If you
- are launching a GUI application, use the C<window_attr> tag instead.
-
- By default, the process shares its parent's console.
-
- =item stdin
-
- An open input filehandle, or the name of an existing file. The resulting
- filehandle will be used for the child's standard input handle.
-
- By default, the child process shares the parent's standard input.
-
- =item stdout
-
- An open output filehandle or filename (will be opened for append). The
- resulting filehandle will be used for the child's standard output handle.
-
- By default, the child process shares the parent's standard output.
-
- =item stderr
-
- An open output filehandle or filename (will be opened for append). The
- resulting filehandle will be used for the child's standard error handle.
-
- By default, the child process shares the parent's standard error.
-
- =back
-
- Unrecognized keys are ignored.
-
- =back
-
- =item 3
-
- 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 I<all> processes to
- complete within the $timeout, or whether to wait for I<any> process to
- complete. You should set this to a boolean, where a true value means to
- wait for I<all> the processes to complete, and a false value to wait
- for I<any>. If you do not specify $which, it defaults to true (C<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;
-
- =item 4
-
- 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;
-
- =item 5
-
- status()
-
- status()
-
- Returns a hash containing information about the processes in the job.
- Only returns valid information I<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 C<exitcode> field should be ignored.
-
- The keys of the hash are the process IDs; the values are a subhash
- containing the following keys:
-
- =over 4
-
- =item exitcode
-
- The exit code returned by the process. If the process was killed because
- of a timeout, the value is 293.
-
- =item time
-
- The time accumulated by the process. This is yet another subhash containing
- the subkeys (i) C<user>, the amount of time the process spent in user
- space; (ii) C<kernel>, the amount of time the process spent in kernel space;
- and (iii) C<elapsed>, the total time the process was running.
-
- =back
-
- =item 6
-
- 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.
-
- =back
-
- =head1 SEE ALSO
-
- 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:
-
- =over 4
-
- =item 1
-
- Win32::Process
-
- Low-level access to creating processes in Win32. See L<Win32::Process>.
-
- =item 2
-
- Win32::Console
-
- Low-level access to consoles in Win32. See L<Win32::Console>.
-
- =item 3
-
- Win32::ProcFarm
-
- Manage pools of threads to perform CPU-intensive tasks on Windows. See
- L<Win32::ProcFarm>.
-
- =back
-
- =head1 AUTHOR
-
- ActiveState (support@ActiveState.com)
-
- =head1 COPYRIGHT
-
- Copyright (c) 2002, ActiveState Corporation. All Rights Reserved.
-
- =cut
-