Forks-Super
view release on metacpan or search on metacpan
lib/Forks/Super.pm view on Meta::CPAN
sub _init_overload {
my ($arg) = @_;
if (defined $arg && $arg =~ /^\d+$/ && $arg == 0) {
Forks::Super::Job::disable_overload();
} else {
Forks::Super::Job::enable_overload();
}
return;
}
sub _import_init_ipc_dir {
my ($ipc_dir) = @_;
if ($ENV{FH_DIR} || $ENV{IPC_DIR} || $ipc_dir) {
# deprecated warning if FH_DIR is set but not IPC_DIR
if ($ENV{FH_DIR} && !$ENV{IPC_DIR}) {
carp "Environment variable 'FH_DIR' is deprecated. Use 'IPC_DIR'\n";
}
Forks::Super::Job::Ipc::set_ipc_dir($ENV{IPC_DIR}, 1)
|| Forks::Super::Job::Ipc::set_ipc_dir($ENV{FH_DIR}, 1)
|| Forks::Super::Job::Ipc::set_ipc_dir($ipc_dir, 1);
}
if (Forks::Super::Job::Ipc::is_cleanse_mode()) {
Forks::Super::Job::Ipc::cleanse($ipc_dir || $IPC_DIR);
exit;
}
return;
}
sub init_pkg {
return if $PKG_INITIALIZED;
$PKG_INITIALIZED++;
Forks::Super::Debug::init();
Forks::Super::Config::init();
# $Forks::Super::SysInfo::MAX_FORK is the point at which your program
# might crash from having too many forks.
#
# Another reasonable default when there are moderately CPU-intensive
# background tasks is ~2*$Forks::Super::SysInfo::NUM_PROCESSORS.
# Default value for $MAX_PROC should be tied to system properties
$DEFAULT_MAX_PROC = $Forks::Super::SysInfo::MAX_FORK - 1;
if ($] < 5.007003) {
$DEFAULT_MAX_PROC = $Forks::Super::SysInfo::NUM_PROCESSORS;
}
$MAX_PROC = $DEFAULT_MAX_PROC;
$MAX_LOAD = -1;
# OK for child process to call Forks::Super::fork()? Could be a bad idea
$CHILD_FORK_OK = 0;
# Disable cleanup of IPC files? Sometimes helpful for debugging.
$DONT_CLEANUP = $ENV{FORKS_DONT_CLEANUP} || 0;
# choose of $Forks::Super::Util::DEFAULT_PAUSE is a tradeoff between
# accuracy/responsiveness and performance.
#
# Low values will make pause/waitpid calls very busy, consuming cpu cycles
#
# High values increase the average delay between the time one job
# finishes and the next waiting job starts.
$Forks::Super::Util::DEFAULT_PAUSE = 0.10; # seconds
$Forks::Super::Util::DEFAULT_PAUSE_IO = 0.05;
*handle_CHLD = *Forks::Super::Sigchld::handle_CHLD;
Forks::Super::Util::set_productive_pause_code {
Forks::Super::Deferred::check_queue();
handle_CHLD(-1);
};
Forks::Super::Wait::set_productive_waitpid_code {
if (&IS_WIN32) {
handle_CHLD(-1);
}
};
tie $ON_BUSY, 'Forks::Super::Tie::Enum', qw(block fail queue);
$ON_BUSY = 'block';
tie $ON_TOO_MANY_OPEN_FILEHANDLES,
'Forks::Super::Tie::Enum', qw(fail rescue);
#$ON_TOO_MANY_OPEN_FILEHANDLES = 'fail';
$ON_TOO_MANY_OPEN_FILEHANDLES = 'rescue'; # enabled v0.85
tie $IPC_DIR, 'Forks::Super::Job::Ipc::Tie';
Forks::Super::Deferred::init();
$XSIG{CHLD}[-1] = \&Forks::Super::handle_CHLD;
no warnings 'redefine','prototype';
*Forks::Super::Impl::fork = \&Forks::Super::Impl::_fork;
*Forks::Super::Impl::wait = \&Forks::Super::Wait::wait;
*Forks::Super::Impl::waitpid = \&Forks::Super::Wait::waitpid;
*Forks::Super::Impl::kill = \&Forks::Super::Impl::_kill;
return;
}
# RT#124316: SIGCHLD handler has unexpected side-effects. When your program
# no longer needs to fork, you can call Forks::Super->deinit_pkg
# to remove those side-effects.
sub deinit_pkg {
untie $ON_BUSY;
untie $ON_TOO_MANY_OPEN_FILEHANDLES;
untie $IPC_DIR;
Forks::Super::Deferred::deinit();
&Forks::Super::Util::set_productive_pause_code(undef);
&Forks::Super::Wait::set_productive_waitpid_code(undef);
undef $XSIG{CHLD}[-1];
if ($] < 5.016000) {
no warnings 'redefine','prototype';
*Forks::Super::Impl::fork = sub { CORE::fork };
*Forks::Super::Impl::wait = sub { CORE::wait };
*Forks::Super::Impl::waitpid = sub { CORE::waitpid($_[0],$_[1]) };
*Forks::Super::Impl::kill = sub { CORE::kill(@_) };
} else {
no warnings 'redefine','prototype';
*Forks::Super::Impl::fork = \&CORE::fork;
*Forks::Super::Impl::wait = \&CORE::wait;
*Forks::Super::Impl::waitpid = \&CORE::waitpid;
*Forks::Super::Impl::kill = \&CORE::kill;
}
$PKG_INITIALIZED = 0;
return;
}
sub Forks::Super::Impl::_fork {
my @fork_args = @_;
my %fork_argsx;
my $opts;
if (ref $fork_args[0] eq 'CODE') {
$fork_argsx{"sub"} = shift @fork_args;
} elsif (ref $fork_args[0] eq 'ARRAY') {
$fork_argsx{"cmd"} = shift @fork_args;
if (@{$fork_argsx{"cmd"}} == 1) {
$fork_argsx{"cmd"} = $fork_argsx{"cmd"}[0];
}
}
if (ref $fork_args[0] ne 'HASH') {
$opts = { @fork_args, %fork_argsx };
} else {
$opts = $fork_args[0];
$opts->{$_} = $fork_argsx{$_} for keys %fork_argsx;
}
$MAIN_PID ||= $$; # initialize on first use
my $job = Forks::Super::Job->new($opts);
$job->_preconfig;
if (defined $job->{__test}) {
return $job->{__test};
}
if (defined $job->{__error}) {
carp $job->{__error};
return undef;
}
if ($job->{debug}) {
debug('fork(): ', $job->toString(), ' initialized.');
}
# handle_CHLD(-1); # <-- benefits MSWin32? or causes memory wrap panic?
while (!$job->can_launch) {
if ($job->{debug}) {
debug("fork(): job can not launch. Behavior=$job->{_on_busy}");
}
if ($job->{_on_busy} eq 'FAIL') {
$job->run_callback('fail');
$job->{end} = Time::HiRes::time();
$job->{status} = -1;
$job->_mark_reaped;
# -1: failure: system is too busy to create a new job
# in $Forks::Super::ON_BUSY documentation
# XXX - document this better?
return -1;
} elsif ($job->{_on_busy} eq 'QUEUE') {
$job->run_callback('queue');
$job->queue_job;
if ($Forks::Super::Job::OVERLOAD_ENABLED) {
return $job;
} else {
return $job->{pid};
}
} else { # BLOCK
pause();
}
}
if ($job->{debug}) {
debug('fork: launch approved for job');
}
# on most systems, $SIG{CHLD}=undef means that the SIGCHLD handler
# we have set up (see Forks::Super::Sigchld) will not get called
# when this child exits. That would be bad, so check for that
# just in case the caller said 'delete $SIG{CHLD}' out of ignorance
# or malice.
if (!defined $SIG{CHLD}) {
# $SIG{CHLD}="\n" warns in openbsd:'SIGCHLD handler "\n" not defined'
$SIG{CHLD} = sub {};
# $SIG{CHLD} = 'IGNORE'; ?
}
return $job->launch;
}
# called from a child process immediately after it
# is created. Mostly this subroutine is about DE-initializing
# the child; removing all the global state that only the
# parent process needs to know about.
sub init_child {
my $is_emulation = shift;
if ($$ == $MAIN_PID && !$is_emulation) {
carp 'Forks::Super::init_child() ',
"method called from main process!\n";
return;
}
Forks::Super::Deferred::init_child();
if (!$is_emulation) {
@ALL_JOBS = ();
# XXX - if $F::S::CHILD_FORK_OK > 0, when do we reset $XSIG{CHLD} ?
$XSIG{CHLD} = [];
$SIG{CHLD} = 'DEFAULT';
Forks::Super::Config::init_child();
}
Forks::Super::Job::init_child();
return;
}
#
# returns the exit status of the given process ID or job ID.
# return undef if we don't think the process is complete yet.
lib/Forks/Super.pm view on Meta::CPAN
# --- impose a time limit on the child process
$pid = fork { cmd => $cmd, timeout => 30 }; # kill child if not done in 30s
$pid = fork { sub => $subRef , args => [ @args ],
expiration => 1260000000 }; # complete 8am Dec 5, 2009 UTC
# --- wait and waitpid support timeouts, too
$pid = wait 3.0;
print "No child reaped in 5s"
if waitpid 0, 0, 5.0 == &Forks::Super::Wait::TIMEOUT;
# --- run a child process starting from a different directory
$pid = fork { dir => "some/other/directory",
cmd => ["command", "--that", "--runs=somewhere", "else"] };
# --- obtain standard file handles for the child process
$pid = fork { child_fh => "in,out,err,:utf8" };
if ($pid == 0) { # child process
sleep 1;
$x = <STDIN>; # read from parent's $pid->{child_stdin} (output handle)
print rand() > 0.5 ? "Yes\n" : "No\n" if $x eq "Clean your room\n";
sleep 2;
$i_can_haz_ice_cream = <STDIN>;
if ($i_can_haz_ice_cream !~ /you can have ice cream/ && rand() < 0.5) {
print STDERR '@#$&#$*&#$*&',"\n";
}
exit 0;
} # else parent process
$child_stdin = $pid->{child_stdin};
$child_stdin = $Forks::Super::CHILD_STDIN{$pid}; # alternate, deprecated
print $child_stdin "Clean your room\n";
sleep 2;
$child_stdout = $pid->{child_stdout};
# -or- $child_stdout = $Forks::Super::CHILD_STDOUT{$pid}; # deprecated
$child_response = <$child_stdout>; # -or-: Forks::Super::read_stdout($pid);
if ($child_response eq "Yes\n") {
print $child_stdin "Good boy. You can have ice cream.\n";
} else {
print $child_stdin "Bad boy. No ice cream for you.\n";
sleep 2;
$child_err = Forks::Super::read_stderr($pid);
# -or- $child_err = $pid->read_stderr();
# -or- $child_err = readline($pid->{child_stderr});
print $child_stdin "And no back talking!\n" if $child_err;
}
# --- retrieve variable values from a child process
$pid1 = fork { share => [ \$scalar, \@list ], sub => \&method };
$pid2 = fork { share => [ \@list, \%hash ], sub => \&someOtherMethod };
waitpid $pid1, 0;
waitpid $pid2, 0;
# now $scalar is set to value in 1st job, @list has values from both jobs,
# and %hash has values from 2nd job
# ---------- manage jobs and system resources ---------------
# --- run 100 tasks but fork blocks while there are already 5 active jobs
$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_LOAD = 2.0;
$Forks::Super::ON_BUSY = 'fail';
$pid = fork { cmd => $task };
if ($pid > 0) { print "'$task' is running\n" }
elsif ($pid < 0) { print "current CPU load > 2.0: didn't start '$task'\n" }
# $Forks::Super::MAX_PROC setting can be overridden.
# Start job 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 { sub => \&MyMethod, force => 1 }
# when system is busy, queue jobs. When system becomes less busy,
# some jobs on the queue will start.
# if job is queued, 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 }; # queue job for at least 20s
# --- assign descriptive names to tasks
$pid1 = fork { cmd => $command, name => "my task" };
$pid2 = waitpid "my task", 0;
$num_signalled = Forks::Super::kill 'TERM', "my task";
$pid1 = fork { cmd => $command1, name => 'task 1' };
$pid2 = fork { cmd => $command2, name => 'task 2' };
$pid = waitpid -1, 0;
print "Task that just finished was $pid->{name}\n"; # task 1 or task 2
# --- run callbacks at various points of job life-cycle
$pid = fork { cmd => $command, callback => \&on_complete };
$pid = fork { sub => $sub, args => [ @args ],
callback => { start => 'on_start', finish => \&on_complete,
queue => sub { print "Job $_[1] queued\n" } } };
# --- set up dependency relationships
$pid1 = fork { cmd => $job1 };
$pid2 = fork { depend_on => $pid1,
cmd => $job2 }; # queue until job 1 is complete
$pid3 = fork { ... };
$pid4 = fork { depend_start => [$pid2,$pid3],
cmd => $job4 }; # queue until jobs 2,3 have started
$pid5 = fork { cmd => $job5, name => "group C" };
$pid6 = fork { cmd => $job6, name => "group C" };
$pid7 = fork { depend_on => "group C",
cmd => $job7 }; # wait for jobs 5 & 6 to complete
# --- manage OS settings on jobs -- may not be available on all systems
$pid1 = fork { os_priority => 10 }; # like nice(1) on Un*x
$pid2 = fork { cpu_affinity => 0x5 }; # background task to prefer CPUs #0,2
# --- job information
$state = Forks::Super::state($pid); # ACTIVE | DEFERRED | COMPLETE | REAPED
$status = Forks::Super::status($pid); # exit status ($?) for completed jobs
# --- return value from fork is object that just looks like a process id
# --- see Forks::Super::Job
$job = fork { ... };
$state = $job->{state};
if ($job->is_complete) {
$status = $job->{status};
}
# --- evaluate long running expressions in the background
$result = bg_eval { a_long_running_calculation() };
# sometime later ...
print "Result was $result\n";
$result = bg_qx( "./long_running_command" );
# ... do something else for a while and when you need the output ...
print "output of long running command was: $result\n";
lib/Forks/Super.pm view on Meta::CPAN
Attaches a string identifier to the job. The identifier can be used
for several purposes:
=over 4
=item *
to obtain a L<Forks::Super::Job|Forks::Super::Job> object
representing the background task through the
L<Forks::Super::Job::get|Forks::Super::Job/"get"> or
L<Forks::Super::Job::getByName|Forks::Super::Job/"getByName"> methods.
=item *
as the first argument to L<"waitpid"> to wait on a job or jobs
with specific names
=item *
as an argument to L<Forks::Super::kill|Forks::Super/"kill"> to
signal a job or group of jobs by name
=item *
to identify and establish dependencies between background
tasks. See the L<"depend_on">
and L<"depend_start"> parameters below.
=item *
if supported by your system, the name attribute will change
the argument area used by the ps(1) program and change the
way the background process is displaying in your process viewer.
(See L<$PROGRAM_NAME in perlvar|perlvar/"$PROGRAM_NAME">
about overriding the special C<$0> variable.)
=back
Each job need not be assigned a unique name. Calls to L<"waitpid">
by name will wait for I<any> job with the specified name, and
calls to L<"kill"> by name will signal I<all> of the jobs with
the specified name.
=back
=head3 max_proc
=over 4
=item C<< fork { max_proc => $max_simultaneous_jobs } >>
=item C<< fork { max_proc => \&subroutine } >>
Specifies the maximum number of background processes that should run
simultaneously. If a C<fork> call is attempted while there are already
the maximum number of child processes running, then the C<fork()>
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 L<"on_busy">, below).
See the L<"Deferred processes"> section for information about
how queued jobs are handled.
On any individual C<fork> call, the maximum number of processes may be
overridden by also specifying C<max_proc> or L<"force"> options.
$Forks::Super::MAX_PROC = 8;
# launch 2nd job only when system is very not busy
# always launch 3rd job no matter how busy we are
$pid1 = fork { sub => 'method1' };
$pid2 = fork { sub => 'method2', max_proc => 1 };
$pid3 = fork { sub => 'method3', force => 1 };
Setting C<max_proc> parameter
to zero or a negative number will disable the check for too many
simultaneous processes. Also see the L<"force"> option, below.
C<max_fork> is a synonym for C<max_proc>.
Also see L<$Forks::Super::MAX_PROC in MODULE VARIABLES|"MAX_PROC">,
which globally specifies the desired maximum number of simultaneous
background processes when a C<max_proc> parameter is not supplied to
the C<fork> call.
Since v0.77, the C<max_proc> parameter may be assigned a code reference
to a subroutine that returns the (possibly dynamic) number of simultaneous
background processes allowed. See
L<$Forks::Super::MAX_PROC in MODULE VARIABLES|"MAX_PROC">
for a use case and demonstration.
=back
=head3 max_load
=over 4
=item C<< fork { max_load => $max_cpu_load } >>
Specifies a maximum CPU load threshold at which this job
can be started. The C<fork>
command will not spawn a new jobs while the current
system CPU load is larger than this threshold.
CPU load checks are disabled if this value is set to zero
or to a negative number.
B<Note that the metric of "CPU load" is different on
different operating systems>.
On Windows (including Cygwin), the metric is CPU
utilization, which is always a value between 0 and 1.
On Unix-ish systems, the metric is the 1-minute system
load average, which could be a value larger than 1.
Also note that the 1-minute average load measurement
has a lot of inertia -- after a CPU intensive task
starts or stops, it will take at least several seconds
for that change to impact the 1-minute utilization.
If your system does not have a well-behaved L<uptime(1)|uptime(1)>
command, then it is recommended to install the
L<Sys::CpuLoadX|Sys::CpuLoadX> module to use this feature.
The C<Sys::CpuLoadX> module is only available bundled with
C<Forks::Super> and otherwise cannot be downloaded from CPAN.
Also see L<$Forks::Super::MAX_LOAD in MODULE VARIABLES|"MAX_LOAD">,
which will specifies the maximum CPU load for launching a job when
the C<max_load> parameter is not provided to C<fork>.
=back
=head3 on_busy
=over 4
=item C<< fork { on_busy => "block" | "fail" | "queue" } >>
Dictates the behavior of C<fork> in the event that the module is not allowed
to launch the specified job for whatever reason. If you are using
C<Forks::Super> to throttle (see
L<max_proc, $Forks::Super::MAX_PROC|"max_proc">)
or impose dependencies on (see L<depend_start|"depend_start">,
L<depend_on|"depend_on">) background processes, then failure to launch a job
should be expected.
=over 4
=item C<block>
If the module 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,
C<fork> calls that use this behavior will return a positive PID.
=item C<fail>
If the module cannot immediately create a new child process
for the specified job, the C<fork> call will return with a
small negative value.
=item C<queue>
If the module 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 L<"Deferred processes">
below. The return
value will be a very negative number (job ID).
=back
Note that jobs that use any of the L<"delay">, L<"start_after">, L<"depend_on">,
or L<"depend_start"> options ignore this setting and always put the job
on the deferred job queue (unless a different C<on_busy> attribute is
explicitly provided).
Also see L<$Forks::Super::ON_BUSY in MODULE VARIABLES|"ON_BUSY">,
which specifies the busy behavior when an C<on_busy> parameter
is not supplied to the C<fork> call.
=back
=head3 force
=over 4
=item C<< fork { force => $bool } >>
If the C<force> option is set, the C<fork> 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.
=back
=head3 queue_priority
=over 4
=item C<< fork { queue_priority => $priority } >>
In the event that a job cannot immediately create a child process and
is put on the job queue (see L<"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.
=back
=head3 depend_on
=head3 depend_start
=over 4
=item C<< fork { depend_on => $id } >>
=item C<< fork { depend_on => [ $id_1, $id_2, ... ] } >>
=item C<< fork { depend_start => $id } >>
=item C<< fork { depend_start => [ $id_1, $id_2, ... ] } >>
Indicates a dependency relationship between the job in this C<fork>
call and one or more other jobs. The identifiers may be
process/job IDs or L<"name"> attributes (see above) from
earlier C<fork> calls.
If a C<fork> call specifies a
C<depend_on> option, then that job will be deferred until
all of the child processes specified by the process or job IDs
have B<completed>. If a C<fork> call specifies a
C<depend_start> option, then that job will be deferred until
all of the child processes specified by the process or job
IDs have B<started>.
Invalid process and job IDs in a C<depend_on> or C<depend_start>
setting will produce a warning message but will not prevent
a job from starting.
Dependencies are established at the time of the C<fork> call
and can only apply to jobs that are known at run time. So for
example, in this code,
$job1 = fork { cmd => $cmd, name => "job1", depend_on => "job2" };
$job2 = fork { cmd => $cmd, name => "job2", depend_on => "job1" };
at the time the first job is cereated, the job named "job2" has not
been created yet, so the first job will not have a dependency (and a
warning will be issued when the job is created). This may
be a limitation but it also guarantees that there will be no
circular dependencies.
When a dependency identifier is a name attribute that applies to multiple
jobs, the job will be dependent on B<all> existing jobs with that name:
# Job 3 will not start until BOTH job 1 and job 2 are done
$job1 = fork { name => "Sally", ... };
$job2 = fork { name => "Sally", ... };
$job3 = fork { depend_on => "Sally", ... };
# all of these jobs have the same name and depend on ALL previous jobs
$job4 = fork {name=>"Ralph", depend_start=>"Ralph", ...}; # no dependencies
$job5 = fork {name=>"Ralph", depend_start=>"Ralph", ...}; # depends on Job 4
$job6 = fork {name=>"Ralph", depend_start=>"Ralph", ...}; # depends on 4 and 5
The default "on_busy" behavior for jobs with dependencies is to go on to
the job queue, ignoring the value of L<$Forks::Super::ON_BUSY/"ON_BUSY">
(but not ignoring the L<< C<on_busy>|"on_busy" >> attribute passed to the
job, if any).
=back
=head3 can_launch
=over 4
=item C<< fork { can_launch => \&methodName } >>
=item C<< 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 C<fork> call or when the job queue is being examined,
the user's C<can_launch> method will be invoked with a single
C<Forks::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 C<_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;
} }
=back
=head3 callback
=over 4
=item C<< fork { callback => $subroutineName } >>
=item C<< fork { callback => sub { BLOCK } } >>
=item C<< fork { callback => { start => ..., finish => ...,
queue => ..., fail => ... } } >>
Install callbacks to be run as certain events in the life cycle
of a background process occur. The first two forms of this option
are equivalent to
fork { callback => { finish => ... } }
and specify code that will be executed when a background process is complete
and the module has received its C<SIGCHLD> event. A C<start> callback is
executed just after a new process is spawned. A C<queue> callback is run
if and only if the job is deferred for any reason
(see L<"Deferred processes">) and
the job is placed onto the job queue for the first time. And the C<fail>
callback is run if the job is not going to be launched (that is, a case
where the C<fork> call would return C<-1>).
Callbacks are invoked with two arguments: the
L<Forks::Super::Job|Forks::Super::Job> object that was created with the original
C<fork> call, and the job's ID (the return value from C<fork>).
You should keep your callback functions short and sweet, like you do
for your signal handlers. Sometimes callbacks are invoked from a
signal handler, and the processing of other signals could be
delayed if the callback functions take too long to run.
=back
=head3 share
=over 4
=item C<< fork { share => [ >> I<list-of-references> C<< ] } >>
Allows variables in the parent process to be updated when the child exits.
Input is a listref of references -- scalar, list, or hash references --
that may be updated in a child process. When the child process finishes,
the values of these variables in the parent are updated with the values
that were in the child on its exit. The value of a scalar variable will
be overwritten with the child value, arrays and hashes will be appended
with the child values.
use Forks::Super;
my $a = 'old value';
my @a = 1..5;
lib/Forks/Super.pm view on Meta::CPAN
=over 4
=item C<< Forks::Super->deinit_pkg >>
=item C<< Forks::Super->init_pkg >>
L<RT#124316|https://rt.cpan.org/Public/Bug/Display.html?id=124316>
identified an issue where the C<SIGCHLD> handler used by
C<Forks::Super> would interfere with a piped open. That is, the
C<close> call in code like
my $pid = open my $fh, "|-", "some command you expect to work ...";
...
close $fh or die "...";
could fail because C<Forks::Super>'s C<SIGCHLD> handler might reap the
process before the implicit C<waitpid> call in the C<close> function
gets to it.
In some situations -- say, near the end of your program, when you
are not going to use C<Forks::Super::fork> anymore, but you
still have a reason to call a piped open -- it is desirable and
appropriate to uninstall C<Forks::Super>'s C<SIGCHLD> handler.
The C<Forks::Super::deinit_pkg> is provided for this purpose.
Forks::Super::deinit_pkg;
Forks::Super->deinit_pkg;
Either one of these calls will uninstall the C<SIGCHLD> handler
and revert the C<fork>, C<waitpid>, C<wait>, and C<kill> functions
to Perl's builtin behaviors. It is a kludgy attempt to "uninstall" the
module, or at least several features of the module, to workaround
the issue with piped opens.
The C<init_pkg> function, invoked as either C<Forks::Super::init_pkg>
or C<< Forks::Super->init_pkg >>, installs features of the module
into your program. It is automatically called when the C<Forks::Super>
module is imported. So it is not necessary for users to call it
explicitly, I<unless> they have previously called C<deinit_pkg>
and wish to I<re-enable> features of the module.
=back
=head1 MODULE VARIABLES
Most module variables may be initialized on the C<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 at run-time:
$Forks::Super::ON_BUSY = 'queue';
$Forks::Super::IPC_DIR = "/home/joe/temp-ipc-files";
Many module variables govern global settings that affect all C<fork> calls.
But many can be overridden by a parameter setting in any
specific C<fork> call.
$Forks::Super::ON_BUSY = 'queue';
$j1 = fork { sub => ... }; # put on queue if busy
$j2 = fork { sub => ..., on_busy = 'block' }; # block if busy
Module variables that may be of interest include:
=head3 MAX_PROC
=over 4
=item C<< $Forks::Super::MAX_PROC = int >>
The maximum number of simultaneous background processes that can
be spawned by C<Forks::Super>. If a C<fork> call is attempted while
there are already at least this many active background processes,
the behavior of the C<fork> call will be determined by the
value in L<$Forks::Super::ON_BUSY|/"ON_BUSY"> or by the
L<"on_busy"> option passed to the C<fork> call.
The L<"force"> option passed to a C<fork> call overrides this
setting. The value might also
not be respected if the user supplies a code reference in the
L<"can_launch"> option and the user-supplied code does not test
whether there are already too many active proceeses.
Since v0.77, the package variable C<$Forks::Super::MAX_PROC> or the
C<max_proc> parameter to C<fork> may be assigned a code reference.
When the module needs to know the maximum
number allowed background processes, it will invoke the subroutine
and expect it to return an integer. Here's a demonstration of how
you could assign a multi-process program to use fewer resources
between 9:00am and 5:00pm:
$Forks::Super::MAX_PROC = sub {
my @lt = localtime;
my $hour = $lt[2];
$hour >= 9 && $hour < 17 ? 4 : 16;
};
=back
=head3 %MAX_PROC
=over 4
=item C<%Forks::Super::MAX_PROC>
Since v0.75. The maximum number of simultaneous
background processes that can be spawned by C<Forks::Super>
and run on a remote host. The keys of this hash are remote
hostnames, and the values are integers specifying how many
jobs can be dispatched to those hosts (see the
L<"remote"> option). The key C<"DEFAULT"> can be used to
provide a default maximum for hosts otherwise not
specified. If a maximum process count for a remote hostname
is not specified in C<%MAX_PROC> and there is not a
C<"DEFAULT"> setting in C<%MAX_PROC>, the maximum number of
processes that can be dispatched to the host defaults to
C<$Forks::Super::MAX_PROC>.
=back
=head3 MAX_LOAD
=over 4
=item C<< $Forks::Super::MAX_LOAD = $max_cpu_utilization >>
The threshold CPU load at which jobs created by a C<fork> call will
be deferred. The metric of "CPU load" means different things
on different operating systems. See the discussion under the
L<"max_load"> parameter to C<fork> for details.
=back
=head3 ON_BUSY
=over 4
=item C<$Forks::Super::ON_BUSY = 'block' | 'fail' | 'queue'>
Determines behavior of a C<fork> call when the system is too
busy to create another background process.
If this value is set to C<block>,
then C<fork> 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 C<fail>, the C<fork> call will return
immediately without launching the background process. The return
value will be C<-1>. A C<Forks::Super::Job> object will not be
created.
If the value is set to C<queue>, then the C<fork> call
will create a "deferred" job that will be queued and run at
a later time. Also see the L<"queue_priority"> option to C<fork>
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 L<"on_busy"> option
supplied to the C<fork> call.
=back
=head3 CHILD_FORK_OK
=over 4
=item C<$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 C<fork()> call
will fail if you try it.
To override this behavior, set C<$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 cannot C<wait> on the
child process of a child process from the main process).
Setting C<$Forks::Super::CHILD_FORK_OK> to a negative value will
disable the functionality of this module in child processes but will
reenable the Perl builtin C<fork()> system call.
Note that this module will not have any preconceptions about which
is the "parent process" until you the first
call to C<Forks::Super::fork>. This means it is possible to use
C<Forks::Super> functionality in processes that were I<not>
spawned by C<Forks::Super>, say, by an explicit C<CORE::fork()> call:
1: use Forks::Super;
2: $Forks::Super::CHILD_FORK_OK = 0;
3:
4: $child1 = CORE::fork();
5: if ($child1 == 0) {
6: # OK -- child1 is still a valid "parent process"
7: $grandchild1 = Forks::Super::fork { ... };
8: ...;
9: exit;
10: }
11: $child2 = Forks::Super::fork();
12: if ($child2 == 0) {
13: # NOT OK - parent of child2 is now "the parent"
14: $grandchild2 = Forks::Super::fork { ... };
15: ...;
16: exit;
17: }
18: $child3 = CORE::fork();
19: if ($child3 == 0) {
20: # NOT OK - call in line 11 made parent of child3 "the parent"
21: $grandchild3 = Forks::Super::fork { ... };
22: ...;
23: exit;
24: }
More specifically, this means it is OK to use the C<Forks::Super>
module in a daemon process:
use Forks::Super;
( run in 1.256 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )