NAME¶
Paranoid::Process - Process Management Functions
VERSION¶
$Id: Process.pm,v 1.01 2010/05/10 04:55:07 acorliss Exp $
SYNOPSIS¶
use Paranoid::Process;
$rv = daemonize();
MAXCHILDREN = 100;
$SIG{CHLD} = \&sigchld;
$count = childrenCount();
installChldHandler($sub);
$rv = pfork();
$uid = ptranslateUser("foo");
$gid = ptranslateGroup("foo");
$rv = switchUser($user, $group);
$rv = pcapture($cmd, \$crv, \$out);
DESCRIPTION¶
This module provides a few functions meant to make life easier when managing
processes. The following export targets are provided:
all All functions within this module
pfork All child management functions
Only the functions
switchUser and
daemonize are currently exported
by default.
SUBROUTINES/METHODS¶
MAXCHILDREN¶
Setting this lvalue subroutine sets a limit to how many children will be forked
at a time by
pfork. The default is zero, which allows unlimited
children. Once the limit is met pfork becomes a blocking call until a child
exits so the new one can be spawned.
childrenCount¶
$count = childrenCount();
This function returns the current number of children spawned by
pfork.
installChldHandler¶
installChldHandler($sub);
This function takes a reference to a subroutine. If used the subroutine will be
called every time a child exits. That subroutine will be called with the
child's PID and exit value as arguments.
sigchld¶
$SIG{CHLD} = \&sigchld;
This function decrements the child counter necessary for pfork's operation, as
well as calling the user's signal handler with each child's PID and exit
value.
daemonize¶
$rv = daemonize();
This function forks a child who reopens all STD* filehandles on /dev/null and
starts a new process group. The parent exits cleanly. If the fork fails for
any reason it returns a false value. The child will also change its directory
to
/.
pfork¶
$rv = pfork();
This function should be used in lieu of Perl's fork if you want to take
advantage of a blocking fork call that respects the MAXCHILDREN limit. Use of
this function, however, also assumes the use of
sigchld as the signal
handler for SIGCHLD.
ptranslateUser¶
$uid = ptranslateUser("foo");
This function takes a username and returns the corresponding UID as returned by
getpwent. If no match is found it returns undef.
ptranslateGroup¶
$gid = ptranslateGroup("foo");
This function takes a group name and returns the corresponding GID as returned
by
getgrent. If no match is found it returns undef.
switchUser¶
$rv = switchUser($user, $group);
This function can be fed one or two arguments, both either named user or group,
or UID or GID. Both user and group arguments are optional as long as the other
is called. In other words, you can pass undef for one of the arguments, but
not for both. If you're only switching the user you can pass only the user
argument.
pcapture¶
$rv = pcapture($cmd, \$crv, \$out);
This function executes the passed shell command and returns one of the following
three values:
RV Description
=======================================================
-1 Command failed to execute or died with signal
0 Command executed but exited with a non-0 RV
1 Command executed and exited with a 0 RV
The actual return value is populated in the passed scalar reference, while all
STDERR/STDOUT output is stored in the last scalar reference. Any errors
executing the command will have the error string stored in
Paranoid::ERROR.
If the command exited cleanly it will automatically be bit shifted eight bits.
NOTE: Unlike many other functions in this suite it is up to you to
detaint the command passed to this function yourself. There's simply no way
for me to know ahead of time what kind of convoluted arguments you might be
handing this call before system is called. Failing to detaint that argument
will cause your script to exit under taint mode.
DEPENDENCIES¶
- o
- Paranoid
- o
- Paranoid::Debug
- o
- POSIX
EXAMPLES¶
pfork¶
This following example caps the number of children processes to three at a time:
$SIG{CHLD} = \&sigchld;
MAXCHILDREN = 3;
for (1 .. 5) {
# Only the children execute the following block
unless ($pid = pfork()) {
# ....
exit 0;
}
}
You can also install a child-exit routine to be called by sigchld. For instance,
to track the children's history in the parent:
sub recordChild ($$) {
my ($cpid, $cexit) = @_;
push(@chistory, [$cpid, $cexit]);
}
installChldHandler(\&recordChild);
for (1 .. 5) {
unless ($pid = pfork()) {
# ....
exit $rv;
}
}
# Prints the child process history
foreach (@chistory) { print "PID: $$_[0] EXIT: $$_[1]\n" };
BUGS AND LIMITATIONS¶
There's a bug in an current versions of Perl where
ptranslateGroup can
return negative numbers instead the actual GID. This is due to the platform
supporting unsigned integers for the GID, but Perl was casting it as a signed
integer. A patch has been submitted to blead-perl.
On Solaris
pcapture doesn't return a -1 for non-existant commands, but a
0. On Linux this appears to work as intended.
AUTHOR¶
Arthur Corliss (corliss@digitalmages.com)
LICENSE AND COPYRIGHT¶
This software is licensed under the same terms as Perl, itself. Please see
http://dev.perl.org/licenses/ for more information.
(c) 2005, Arthur Corliss (corliss@digitalmages.com)