NAME
Forks::Super - extensions and convenience methods for managing background processes.
VERSION
Version 0.06
SYNOPSIS
use Forks::Super;
use Forks::Super MAX_PROC => 5, DEBUG => 1;
# familiar use - parent return PID>0, child returns zero
$pid = fork();
die "fork failed" unless defined $pid;
if ($pid > 0) {
# parent code
} else {
# child code
}
# wait for a child process to finish
$w = wait; # blocking wait for any child, $? hold exit status of child
$w = waitpid $pid, 0; # blocking wait for specific child
$w = waitpid $pid, WNOHANG; # non blocking wait, use with POSIX ':sys_wait_h'
$w = waitpid 0, $flag; # wait on any process in the current process group
waitall; # block until all children are finished
# -------------- helpful extensions ---------------------
# fork directly to a shell command. Child doesn't return.
$pid = fork { cmd => "./myScript 17 24 $n" };
$pid = fork { cmd => [ "/bin/prog" , $file, "-x", 13 ] };
# fork directly to a Perl subroutine. Child doesn't return.
$pid = fork { 'sub' => $methodNameOrRef , 'args' = [ @methodArguments ] };
$pid = fork { 'sub' => \&subroutine, 'args' = [ @args ] };
$pid = fork { 'sub' => sub { "anonymous sub" }, 'args' = [ @args ] );
# put a time limit on the child process
$pid = fork { cmd => $command, timeout => 30 }; # kill child if not done in 30s
$pid = fork { sub => $subRef , expiration => 1260000000 }; # complete by 8AM Dec 5, 2009 UTC
# obtain standard filehandles for the child process
$pid = fork { get_child_filehandles => 1 };
if ($pid == 0) { # child process
$x = <STDIN>; # read "Clean your room" command from parent
print "from the mouth of babes\n"; # same as print STDOUT ...
print STDERR "oops, child is crying\n";
exit 0;
} elsif ($pid > 0) { # parent process
print {$Forks::Super::CHILD_STDIN{$pid}} "Clean your room\n";
$child_response = < {$Forks::Super::CHILD_STDOUT{$pid}} >; # read "from the mouth of babes" from child
$child_response = Forks::Super::read_stdout($pid); # same as <{$Forks::Super::CHILD_STDOUT{$pid}}>
$child_err_msg = < {$Forks::Super::CHILD_STDERR{$pid}} >; # read "oops, child is crying"
$child_err_msg = Forks::Super::read_stderr($pid); # same as <{$Forks::Super::CHILD_STDERR{$pid}}>
}
# ---------- manage jobs and system resources ---------------
# this runs 100 tasks but the fork call blocks when there are already 5 jobs running
$Forks::Super::MAX_PROC = 5;
$Forks::Super::ON_BUSY = 'block';
for ($i=0; $i<100; $i++) {
$pid = fork { cmd => $task[$i] };
}
# jobs fail (without blocking) if the system is too busy
$Forks::Super::MAX_PROC = 5;
$Forks::Super::ON_BUSY = 'fail';
$pid = fork { cmd => $task };
if ($pid > 0) { print "'$task' is running\n" }
elsif ($pid < 0) { print "5 or more jobs running -- didn't start '$task'\n"; }
# $Forks::Super::MAX_PROC setting can be overridden. This job will start immediately if < 3 jobs running
$pid = fork { sub => 'MyModule::MyMethod', args => [ @b ], max_proc => 3 };
# try to fork no matter how busy the system is
$pid = fork { force => 1 };
# when system is busy, queue jobs. When system is not busy, some jobs on the queue will start.
# if job is queue, return value from fork() is a very negative number
$Forks::Super::ON_BUSY = 'queue';
$pid = fork { cmd => $command };
$pid = fork { cmd => $useless_command, queue_priority => -5 };
$pid = fork { cmd => $important_command, queue_priority => 5 };
$pid = fork { cmd => $future_job, delay => 20 } # put this job on queue for at least 20s
# set up dependency relationships
$pid1 = fork { cmd => $job1 };
$pid2 = fork { cmd => $job2, depend_on => $pid1 }; # put on queue until job 1 is complete
$pid4 = fork { cmd => $job4, depend_start => [$pid2,$pid3] }; # put on queue until jobs 2,3 have started
# job information
$state = Forks::Super::state($pid); # ACTIVE, DEFERRED, COMPLETE, REAPED
$status = Forks::Super::status($pid); # exit status for completed jobs
DESCRIPTION
This package provides new definitions for the Perl functions fork
, wait
, and waitpid
with richer functionality. The new features are designed to make it more convenient to spawn background processes and more convenient to manage them and to get the most out of your system's resources.
$pid = fork( \%options )
The new fork
call attempts to spawn a new process. With no arguments, it behaves the same as the Perl system call fork()
:
creating a new process running the same program at the same point
returning the process id (PID) of the child process to the parent
On Windows, this is a pseudo-process ID
returning 0 to the child process
returning
undef
if the fork call was unsuccessful
Options for instructing the child process
The fork
call supports two options, cmd
and sub
(or sub
/args
) that will instruct the child process to carry out a specific task. Using either of these options causes the child process not to return from the fork
call.
- $child_pid = fork { cmd => $shell_command }
- $child_pid = fork { cmd => @shell_command }
-
On successful launch of the child process, runs the specified shell command in the child process with the Perl
system()
function. When the system call is complete, the child process exits with the same exit status that was returned by the system call.Returns the PID of the child process to the parent process. Does not return from the child process, so you do not need to check the fork() return value to determine whether code is executing in the parent or child process.
- $child_pid = fork { sub => $subroutineName [, args => \@args ] }
- $child_pid = fork { sub => \&subroutineReference [, args => \@args ] }
- $child_pid = fork { sub => sub { ... subroutine defn ... } [, args => \@args ] }
-
On successful launch of the child process,
fork
invokes the specified Perl subroutine with the specified set of method arguments (if provided). If the subroutine completes normally, the child process exits with a status of zero. If the subroutine exits abnormally (i.e., if itdie
s, or if the subroutine invokesexit
with a non-zero argument), the child process exits with non-zero status.Returns the PID of the child process to the parent process. Does not return from the child process, so you do not need to check the fork() return value to determine whether code is running in the parent or child process.
If neither the
cmd
or thesub
option is provided to the fork call, then the fork() call behaves like a Perlfork()
call, returning the child PID to the parent and also returning zero to the child.
Options for simple job management
- fork { timeout => $delay_in_seconds }
- fork { expiration => $timestamp_in_seconds_since_epoch_time }
-
Puts a deadline on the child process and causes the child to
die
if it has not completed by the deadline. With thetimeout
option, you specify that the child process should not survive longer than the specified number of seconds. Withexpiration
, you are specifying an epoch time (like the one returned by thetime
function) as the child process's deadline.If the deadline is some time in the past (if the timeout is not positive, or the expiration is earlier than the current time), then the child process will die immediately after it is created.
Note that this feature uses the Perl
alarm
call with a handler forSIGALRM
. If you use this feature and also specify asub
to invoke, and that subroutine also tries to use thealarm
feature or set a handler forSIGALRM
, the results will be undefined. - fork { delay => $delay_in_seconds }
- fork { start_after => $timestamp_in_epoch_time }
-
Causes the child process to be spawned at some time in the future. The return value from a
fork
call that uses these features will not be a process id, but it will be a very negative number called a job ID. See the section on "Deferred Processes" for information on what to do with a job ID.A deferred job will start no earlier than its appointed time in the future. Depending on what circumstances the queued jobs are examined, the actual start time of the job could be significantly later than the appointed time.
A job may have both a minimum start time (through
delay
orstart_after
options) and a maximum end time (throughtimeout
andexpiration
). Jobs with inconsistent times (end time is not later than start time) will be killed of as soon as they are created. - fork { get_child_filehandles => 1 }
- fork { get_child_stdin => $bool, get_child_stdout => $bool, get_child_stderr => $bool }
- fork { get_child_stdout => $bool, join_child_stderr => $bool }
-
Launches a child process and makes the child process's STDIN, STDOUT, and/or STDERR filehandles available to the parent process in the scalar variables $Forks::Super::CHILD_STDIN{$pid}, $Forks::Super::CHILD_STDOUT{$pid}, and/or $Forks::Super::CHILD_STDERR{$pid}, where $pid is the PID return value from the fork call. This feature makes it possible, even convenient, for a parent process to communicate with a child, as this contrived example shows.
$pid = fork { sub => \&pig_latinize, timeout => 10, get_child_filehandles => 1 }; # in the parent, $Forks::Super::CHILD_STDIN{$pid} is an *output* filehandle print {$Forks::Super::CHILD_STDIN{$pid}} "The blue jay flew away in May\n"; sleep 2; # give child time to do its job # and $Forks::Super::CHILD_STDOUT{$pid} is an *input* handle $result = <{$Forks::Super::CHILD_STDOUT{$pid}}>; print "Pig Latin translator says: $result\n"; # ==> eThay ueblay ayjay ewflay awayay inay ayMay\n @errors = <{$Forks::Super::CHILD_STDERR{$pid}>; print "Pig Latin translator complains: @errors\n" if @errors > 0; sub pig_latinize { for (;;) { while (<STDIN>) { foreach my $word (split /\s+/) { if ($word =~ /^qu/i) { print substr($word,2) . substr($word,0,2) . "ay"; # STDOUT } elsif ($word =~ /^([b-df-hj-np-tv-z][b-df-hj-np-tv-xz]*)/i) { my $prefix = 1; $word =~ s/[b-df-hj-np-tv-z][b-df-hj-np-tv-xz]*//i; print $word . $prefix . "ay"; } elsif ($word =~ /^[aeiou]/i) { print $word . "ay"; } else { print STDERR "Didn't recognize this word: $word\n"; } print " "; } print "\n"; } } }
The option
get_child_filehandles
will obtain filehandles for the child's STDIN, STDOUT, and STDERR filehandles. Ifget_child_filehandles
is omitted, the fork() call will obtain those filehandles specified withget_child_stdin
,get_child_stdout
, and/orget_child_stderr
options. If thejoin_child_stderr
option is specified, then both the child's STDOUT and STDERR will be returned in the single $Forks::Super::CHILD_STDOUT{$pid} filehandle.
Options for complicated job management
The fork()
call from this module supports options that help to manage child processes or groups of child processes in ways to better manage your system's resources. For example, you may have a lot of tasks to perform in the background, but you don't want to overwhelm your (possibly shared) system by running them all at once. There are features to control how many, how, and when your jobs will run.
- $Forks::Super::MAX_PROC = $max_simultaneous_jobs
-
Specifies the maximum number of background processes that you want to run. If a
fork
call is attempted while there are already the maximum number of child processes running, then thefork()
call will either block (until some child processes complete), fail (return a negative value without spawning the child process), or queue the job (returning a very negative value called a job ID), according to the specified "on_busy" behavior (see the next item). See the "Deferred processes" section for information about how queued jobs are handled.On any individual
fork
call, the maximum number of processes may be overridden by also specifyingmax_proc
orforce
options. See below.Setting $Forks::Super::MAX_PROC to zero or a negative number will disable the check for too many simultaneous processes.
- $Forks::Super::ON_BUSY = "block" | "fail" | "queue"
-
Dictates the behavior of
fork
in the event that the module is not allowed to launch the specified job for whatever reason.- "block"
-
If the system cannot create a new child process for the specified job, it will wait and periodically retry to create the child process until it is successful. Unless a system fork call is attempted and fails,
fork
calls that use this behavior will return a positive PID. - "fail"
-
If the system cannot create a new child process for the specified job, the
fork
call will immediately return with a small negative value. - "queue"
-
If the system cannot create a new child process for the specified job, the job will be deferred, and an attempt will be made to launch the job at a later time. See "Deferred processes" below. The return value will be a very negative number (job ID).
On any individual
fork
call, the default launch failure behavior specified by $Forks::Super::ON_BUSY can be overridden by specifying aon_busy
option:$Forks::Super::ON_BUSY = "fail"; $pid1 = fork { sub => 'myMethod' }; $pid2 = fork { sub => 'yourMethod', on_busy => "queue" }
- fork { force => $bool }
-
If the
force
option is set, thefork
call will disregard the usual criteria for deciding whether a job can spawn a child process, and will always attempt to create the child process. - fork { queue_priority => $priority }
-
In the event that a job cannot immediately create a child process and is put on the job queue (see "Deferred processes"), the C{queue_priority} specifies the relative priority of the job on the job queue. In general, eligible jobs with high priority values will be started before jobs with lower priority values.
- fork { depend_on => $pid }
- fork { depend_on => [ $pid_1, $pid_2, ... ] }
- fork { depend_start => $pid }
- fork { depend_start => [ $pid_1, $pid_2, ... ] }
-
Indicates a dependency relationship between the job in this
fork
call and one or more other jobs. If afork
call specifies adepend_on
option, then that job will be deferred until all of the child processes specified by the process or job IDs have completed. If afork
call specifies adepend_start
option, then that job will be deferred until all of the child processes specified by the process or job IDs have started.Invalid process and job IDs in a
depend_on
ordepend_start
setting will produce a warning message but will not prevent a job from starting. - fork { can_launch = \&methodName }
- fork { can_launch = sub { ... anonymous sub ... } }
-
Supply a user-specified function to determine when a job is eligible to be started. The function supplied should return 0 if a job is not eligible to start and non-zero if it is eligible to start.
During a
fork
call or when the job queue is being examined, the user'scan_launch
method will be invoked with a singleForks::Super::Job
argument containing information about the job to be launched. User code may make use of the default launch determination method by invoking the_can_launch
method of the job object:# Running on a BSD system with the uptime(1) call. # Want to block jobs when the current CPU load # (1 minute) is greater than 4 and respect all other criteria: fork { cmd => $my_command, can_launch => sub { $job = shift; # a Forks::Super::Job object return 0 if !$job->_can_launch; # default $cpu_load = (split /\s+/,`uptime`)[-3]; # get 1 minute avg CPU load return 0 if $cpu_load > 4.0; # system too busy. let's wait return 1; } }
- fork { os_priority => $priority }
-
On supported operating systems, and after the successful creation of the child process, attempt to set the operating system priority of the child process.
Deferred processes
Whenever some condition exists that prevents a fork()
call from immediately starting a new child process, an option is to defer the job. Deferred jobs are placed on a queue. At periodic intervals, in response to periodic events, or whenever you invoke the Forks::Super::run_queue
method in your code, the queue will be examined to see if any deferred jobs are eligible to be launched.
Job ID
When a fork()
call fails to spawn a child process but instead defers the job by adding it to the queue, the fork()
call will return a unique, large negative number called the job ID. The number will be negative and large enough (<= -100000) so that it can be distinguished from any possible PID, Windows pseudo-process ID, process group ID, or fork()
failure code.
Although the job ID is not the actual ID of a system process, it may be used like a PID as an argument to waitpid
, as a dependency specification in another fork
call's depend_on
or depend_start
option, or the other module methods used to retrieve job information (See "Obtaining job information" below). Once a deferred job has been started, it will be possible to obtain the actual PID (or on Windows, the actual psuedo-process ID) of the process running that job.
Job priority
Every job on the queue will have a priority value. A job's priority may be set explicitly by including the queue_priority
option in the fork()
call, or it will be assigned a default priority near zero. Every time the queue is examined, the queue will be sorted by this priority value and an attempt will be made to launch each job in this order. Note that different jobs may have different criteria for being launched, and it is possible that that an eligible low priority job may be started before an ineligible higher priority job.
Queue examination
Certain events in the SIGCHLD
handler or in the wait
, waitpid
, and/or waitall
methods will cause the list of deferred jobs to be evaluated and to start eligible jobs. But this configuration does not guarantee that the queue will be examined in a timely or frequent enough basis. The user may invoke the
Forks::Super::run_queue()
method at any time to cause the queue to be examined.
Special tips for Windows systems
On POSIX systems (including Cygwin), programs using the Forks
module are interrupted when a child process completes. A callback function performs some housekeeping and may perform other duties like trying to dispatch things from the list of deferred jobs.
Windows systems do not have the signal handling capabilities of other systems, and so other things equal, a script running on Windows will not perform the housekeeping tasks as frequently as a script on other systems.
The method Forks::Super::pause
can be used as a drop in replacement for the Perl sleep
call. In a pause
function call, the program will check on active child processes, reap the ones that have completed, and attempt to dispatch jobs on the queue.
Calling pause
with an argument of 0 is also a valid way of invoking the child handler function on Windows. When used this way, pause
returns immediately after running the child handler.
Child processes are implemented differently in Windows than in POSIX systems. The CORE::fork
and Forks::Super::fork
calls will usually return a pseudo-process ID to the parent process, and this will be a negative value. The Unix idiom of testing whether a fork
call returns a positive number needs to be modified on Windows systems by testing whether Forks::Super::isValidPid($pid)
returns true, where $pid
is the return value from a Forks::Super::fork
call.
OTHER FUNCTIONS
- $reaped_pid = wait
-
Like the Perl
wait
system call, blocks until a child process terminates and returns the PID of the deceased process, or-1
if there are no child processes remaining to reap. The exit status of the child is returned in $?. - $reaped_pid = waitpid $pid, $flags
-
Waits for a child with a particular PID or a child from a particular process group to terminate and returns the PID of the deceased process, or
-1
if there is no suitable child process to reap. If the return value contains a PID, then $? is set to the exit status of that process.A valid job ID (see "Deferred processes") may be used as the $pid argument to this method. If the
waitpid
call reaps the process associated with the job ID, the return value will be the actual PID of the deceased child.Note that the
waitpid
function can wait on a job ID even when the job associated with that ID is still in the job queue, waiting to be started.A $pid value of
-1
waits for the first available child process to terminate and returns its PID.A $pid value of
0
waits for the first available child from the same process group of the calling process.A negative $pid that is not recognized as a valid job ID will be interpreted as a process group ID, and the
waitpid
function will return the PID of the first available child from the same process group.On some systems, a $flags value of
POSIX::WNOHANG
is supported to perform a non-blocking wait. See the Perlwaitpid
documentation. - waitall
-
Blocking wait for all child processes, including deferred jobs that have not started at the time of the
waitall
call. - Forks::Super::isValidPid( $pid )
-
Tests whether the return value of a
fork
call indicates that a background process was successfully created or not. On POSIX systems it is sufficient to check whether$pid
is a positive integer, butisValidPid
is a more - Forks::Super::pause($delay)
-
A productive drop-in replacement for the Perl
sleep
system call (orTime::HiRes::sleep
, if available). On systems like Windows that lack a proper method for handlingSIGCHLD
events, theForks::Super::pause
method will occasionally reap child processes that have completed and attempt to dispatch jobs on the queue.On other systems, using
Forks::Super::pause
is less vulnerable thansleep
to interruptions from this module (See "BUGS AND LIMITATIONS" below). - Forks::Super::child_exit($code)
-
The
child_exit
routine can be used as a drop in replacement ofexit
on a child process. Someday I'll think of some child clean up code to put in there and encourage you to use it. - $status = Forks::Super::status($pid)
-
Returns the exit status of a completed child process represented by process ID or job ID $pid. Aside from being a permanent store of the exit status of a job, using this method might be a more reliable indicator of a job's status than checking $? after a
wait
orwaitpid
call. It is possible for this module'sSIGCHLD
handler to temporarily corrupt the $? value while it is checking for deceased processes. - $line = Forks::Super::read_stdout($pid)
- @lines = Forks::Super::read_stdout($pid)
- $line = Forks::Super::read_stderr($pid)
- @lines = Forks::Super::read_stderr($pid)
-
For jobs that were started with the
get_child_stdout
andget_child_stderr
options enabled, read data from the STDOUT and STDERR filehandles of child processes.Aside from the more readable syntax, these functions may be preferable to
@lines = < {$Forks::Super::CHILD_STDOUT{$pid}} >; $line = < {$Forks::Super::CHILD_STDERR{$pid}} >;
because they will automatically handle clearing the EOF condition on the filehandles if the parent is reading on the filehandles faster than the child is writing on them.
Functions work in both scalar and list context. If there is no data to read on the filehandle, but the child process is still active and could put more data on the filehandle, these functions return "" in scalar and list context. If there is no more data on the filehandle and the child process is finished, the functions return
undef
. - $job = Forks::Super::Job::get($pid)
-
Returns a
Forks::Super::Job
object associated with process ID or job ID$pid
. See Forks::Super::Job for information about the methods and attributes of these objects.
MODULE VARIABLES
Module variables may be initialized on the use Forks::Super
line
# set max simultaneous procs to 5, allow children to call CORE::fork()
use Forks::Super MAX_PROC => 5, CHILD_FORK_OK => -1;
or they may be set explicitly in the code:
$Forks::Super::ON_BUSY = 'queue';
$Forks::Super::FH_DIR = "/home/joe/temp-ipc-files";
Module variables that may be of interest include:
Previous sections discussed the use of $Forks::Super::MAX_PROC
and $Forks::Super::ON_BUSY
. Some other module variables that might be of interest are
- $Forks::Super::MAX_PROC
-
The maximum number of simultaneous background processes that can be spawned by
Forks::Super
. If afork
call is attempted while there are already at least this many active background processes, the behavior of thefork
call will be determined by the value in$Forks::Super::ON_BUSY
or by theon_busy
option passed to thefork
call.This value will be ignored during a
fork
call if theforce
option is passed tofork
with a non-zero value. The value might also not be respected if the user supplies a code reference in thecan_launch
option and the user-supplied code does not test whether there are already too many active proceeses. - $Forks::Super::ON_BUSY = 'block' | 'fail' | 'queue'
-
Determines behavior of a
fork
call when the system is too busy to create another background process.If this value is set to
block
, thenfork
will wait until the system is no longer too busy and then launch the background process. The return value will be a normal process ID value (assuming there was no system error in creating a new process).If the value is set to
fail
, thefork
call will return immediately without launching the background process. The return value will be-1
. AForks::Super::Job
object will not be created.If the value is set to
queue
, then thefork
call will create a "deferred" job that will be queued and run at a later time. Also see thequeue_priority
option tofork
to set the urgency level of a job in case it is deferred. The return value will be a large and negative job ID.This value will be ignored in favor of an
on_busy
option supplied to thefork
call. - $Forks::Super::CHILD_FORK_OK = -1 | 0 | +1
-
Spawning a child process from another child process with this module has its pitfalls, and this capability is disabled by default: you will get a warning message and the
fork()
call will fail if you try it.To override hits behavior, set
$Forks::Super::CHILD_FORK_OK
to a non-zero value. Setting it to a positive value will allow you to use all the functionality of this module from a child process (with the obvious caveat that you cannotwait
on the child process or a child process from the main process).Setting
$Forks::Super::CHILD_FORK_OK
to a negative value will disable the functionality of this module but will reenable the classic Perlfork()
system call from child processes. - $Forks::Super::DEBUG, Forks::Super::DEBUG
-
To see the internal workings of the
Forks
module, set$Forks::Super::DEBUG
to a non-zero value. Information messages will be written to theForks::Super::DEBUG
filehandle. By defaultForks::Super::DEBUG
is aliased toSTDERR
, but it may be reset by the module user at any time. - %Forks::Super::CHILD_STDIN
- %Forks::Super::CHILD_STDOUT
- %Forks::Super::CHILD_STDERR
-
In jobs that request access to the child process filehandles, these hash arrays contain filehandles to the standard input and output streams of the child. The filehandles for particular jobs may be looked up in these tables by process ID or job ID for jobs that were deferred.
Remember that from the perspective of the parent process,
$Forks::Super::CHILD_STDIN{$pid}
is an output filehandle (what you print to this filehandle can be read in the child's STDIN), and$Forks::Super::CHILD_STDOUT{$pid}
and$Forks::Super::CHILD_STDERR{$pid}
are input filehandles (for reading what the child wrote to STDOUT and STDERR).As with any asynchronous communication scheme, you should be aware of how to clear the EOF condition on filehandles that are being simultaneously written to and read from by different processes. A scheme like this works on most systems:
# in parent, reading STDOUT of a child for (;;) { while (<{$Forks::Super::CHILD_STDOUT{$pid}}>) { print "Child $pid said: $_"; } # EOF reached, but child may write more to filehandle later. sleep 1; seek $Forks::Super::CHILD_STDOUT{$pid}, 0, 1; }
- @Forks::Super::ALL_JOBS, %Forks::Super::ALL_JOBS
-
List of all
Forks::Super::Job
objects that were created fromfork()
calls, including deferred and failed jobs. Both process IDs and job IDs (for jobs that were deferred at one time) can be used to look up Job objects in the %Forks::Super::ALL_JOBS table.
DIAGNOSTICS
fork() not allowed in child process ...
Forks::Super::fork() call not allowed in child process ...
-
When the package variable
$Forks::Super::CHILD_FORK_OK
is zero, this package does not allow thefork()
method to be called from a child process. Set$Forks::Super::CHILD_FORK_OK
to change this behavior. quick timeout
-
A job was configured with a timeout/expiration time such that the deadline for the job occurred before the job was even launched. The job was killed immediately after it was spawned.
Job start/Job dependency <nnn> for job <nnn> is invalid. Ignoring.
-
A process id or job id that was specified as a
depend_on
ordepend_start
option did not correspond to a known job. Job <nnn> reaped before parent initialization.
-
A child process finished quickly and was reaped by the parent process SIGCHLD handler before the parent process could even finish initializing the job state. The state of the job in the parent process might be unavailable or corrupt for a short time, but eventually it should be all right.
interprocess filehandles not available
could not open filehandle to provide child STDIN/STDOUT/STDERR
child was not able to detect STDIN file ... Child may not have any input to read.
could not open filehandle to write child STDIN
could not open filehandle to read child STDOUT/STDERR
-
Initialization of filehandles for a child process failed. The child process will continue, but it will be unable to receive input from the parent through the
$Forks::Super::CHILD_STDIN{pid}
filehandle, or pass output to the parent through the filehandles$Forks::Super::CHILD_STDOUT{PID}
AND$Forks::Super::CHILD_STDERR{pid}
.
INCOMPATIBILITIES
If a fork
call ever results in a task being deferred, then this module will install a SIGUSR1
handler as well, and become incompatible with modules that require their own SIGUSR1
handler.
Some features use the alarm
function and custom SIGALRM
handlers in the child processes. Using other modules that employ this functionality may cause undefined behavior. Systems and versions that do not implement the alarm
function (like MSWin32 prior to Perl v5.7) will not be able to use these features.
DEPENDENCIES
There are no hard module dependencies in this module on anything that is not distributed with core Perl. This module is capable of making use of other modules, if available:
Time::HiRes
BUGS AND LIMITATIONS
A typical script using this module will have a lot of behind-the-scenes signal handling as child processes finish and are reaped. These frequent interruptions can affect the execution of your program. For example, in this script:
1: use Forks::Super;
2: fork(sub => sub { sleep 2 });
3: sleep 5;
4: # ... program continues ...
the sleep
call in line 3 is probably going to get interrupted before 5 seconds have elapsed as the end of the child process spawned in line 2 will interrupt execution and invoke the SIGCHLD handler. In some cases there are tedious workarounds:
3a: $stop_sleeping_at = time + 5;
3b: sleep 1 while time < $stop_sleeping_at;
It should be noted that signal handling in Perl is much improved with version 5.6, and the problems caused by such interruptions are much more tractable than they used to be.
The system implementation of fork'ing and wait'ing varies from platform to platform. It is possible that this module or certain features will not work as advertised. Please report any problems you encounter to <mob@cpan.org> and I'll see what I can do about it.
AUTHOR
Marty O'Brien, <mob@cpan.org>
LICENSE AND COPYRIGHT
Copyright (c) 2009, Marty O'Brien.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.