.\" -*- mode: troff; coding: utf-8 -*- .\" Automatically generated by Pod::Man 5.01 (Pod::Simple 3.43) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. .ie n \{\ . ds C` "" . ds C' "" 'br\} .el\{\ . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Paranoid::Process 3pm" .TH Paranoid::Process 3pm 2024-03-07 "perl v5.38.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH NAME Paranoid::Process \- Process Management Functions .SH VERSION .IX Header "VERSION" \&\f(CW$Id:\fR lib/Paranoid/Process.pm, 2.10 2022/03/08 00:01:04 acorliss Exp $ .SH SYNOPSIS .IX Header "SYNOPSIS" .Vb 1 \& use Paranoid::Process qw(:all); \& \& $rv = daemonize(); \& \& MAXCHILDREN = 100; \& \& $SIG{CHLD} = \e&sigchld; \& $count = childrenCount(); \& installChldHandler(&cleanup); \& $rv = pfork(); \& $rv = pcommFork($rh, $wh); \& \& $uid = ptranslateUser("foo"); \& $gid = ptranslateGroup("foo"); \& $rv = switchUser($user, $group); \& \& $rv = pcapture($cmd, $crv, $out); \& \& installSIGH(\*(AqINT\*(Aq, &sigint1): \& installSIGH(\*(AqINT\*(Aq, &sigint2): \& installSIGH(\*(AqINT\*(Aq, &sigint3): \& \& uninstallSIGH(\*(AqINT\*(Aq, &sigint2); \& \& installSIGD(); \& uninstallSIGD(); .Ve .SH DESCRIPTION .IX Header "DESCRIPTION" This module provides a few functions meant to make life easier when managing processes. .SH "IMPORT LISTS" .IX Header "IMPORT LISTS" This module exports the following symbols by default: .PP .Vb 1 \& switchUser daemonize .Ve .PP The following specialized import lists also exist: .PP .Vb 9 \& List Members \& \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \& misc pcapture \& pfork MAXCHILDREN childrenCount installChldHandler \& sigchld pfork pcommFork daemonize \& signal installSIGH uninstallSIGH installSIGD \& uninstallSIGD \& user switchUser ptranslateUser ptranslateGroup \& all @misc @pfork @signal @user .Ve .SH "IMPORT LISTS" .IX Header "IMPORT LISTS" This module exports the following symbols by default: .PP .Vb 1 \& switchUser daemonize .Ve .PP The following specialized import lists also exist: .PP .Vb 8 \& List Members \& \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \& pfork MAXCHILDREN childrenCount installChldHandler \& sigchld pfork pcommFork daemonize \& signal installSIGH uninstallSIGH installSIGD \& uninstallSIGD \& user switchUser ptranslateUser ptranslateGroup \& misc pcapture .Ve .SH SUBROUTINES/METHODS .IX Header "SUBROUTINES/METHODS" .SS MAXCHILDREN .IX Subsection "MAXCHILDREN" Setting this lvalue subroutine sets a limit to how many children will be forked at a time by \fBpfork\fR. 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. .PP \&\fBNOTE:\fR This limit on children is enforced on a per-process basis. That means that while a process is limited to the max threshold, its children could also fork their own batch of children as well, up to whatever max is set in those processes. .SS childrenCount .IX Subsection "childrenCount" .Vb 1 \& $count = childrenCount(); .Ve .PP This function returns the current number of children spawned by \fBpfork\fR. .SS installChldHandler .IX Subsection "installChldHandler" .Vb 1 \& installChldHandler(&cleanup); .Ve .PP This function takes a reference to a subroutine. If used the subroutine will be called every time a child exits and triggers sigchild. That subroutine will be called with the child's PID and exit value as arguments. .SS sigchld .IX Subsection "sigchld" .Vb 1 \& $SIG{CHLD} = \e&sigchld; \& \& # Or, if using the signal dispatcher \& installSIGH(\*(AqCHLD\*(Aq, &sigchld); \& installSIGD(); .Ve .PP 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. .SS daemonize .IX Subsection "daemonize" .Vb 1 \& $rv = daemonize(); .Ve .PP 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 \fB/\fR. .SS pfork .IX Subsection "pfork" .Vb 1 \& $rv = pfork(); .Ve .PP 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 \fBsigchld\fR as the signal handler for SIGCHLD. .SS pcommFork .IX Subsection "pcommFork" .Vb 1 \& $rv = pcommFork($rh, $wh); .Ve .PP This function extends \fBpfork\fR by automatically setting up bidirectional pipes for interprocess communication. The two scalars passed as arguments will have the appropriate ends of the pipe returned to both the parent and the child. .PP In the event that a fork fails, \fBundef\fR will be assigned to both scalars. .PP The return value will be the result of the \fBfork\fR call. .SS ptranslateUser .IX Subsection "ptranslateUser" .Vb 1 \& $uid = ptranslateUser("foo"); .Ve .PP This function takes a username and returns the corresponding UID as returned by \fBgetpwent\fR. If no match is found it returns undef. .SS ptranslateGroup .IX Subsection "ptranslateGroup" .Vb 1 \& $gid = ptranslateGroup("foo"); .Ve .PP This function takes a group name and returns the corresponding GID as returned by \fBgetgrent\fR. If no match is found it returns undef. .SS switchUser .IX Subsection "switchUser" .Vb 2 \& $rv = switchUser($user); \& $rv = switchUser($user, $group); .Ve .PP 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 one of them is defined. .SS pcapture .IX Subsection "pcapture" .Vb 1 \& $rv = pcapture($cmd, $crv, $out); .Ve .PP This function executes the passed shell command and returns one of the following three values: .PP .Vb 5 \& 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 .Ve .PP The actual return value is populated in the passed scalar, while all command output (including STDERR) is stored in the next scalar. Any errors executing the command will have the error string stored in \fBParanoid::ERROR\fR. .PP If the command exited cleanly it will automatically be bit shifted eight bits. .PP \&\fBNOTE:\fR 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. .SS installSIGH .IX Subsection "installSIGH" .Vb 1 \& installSIGH($signal, &subroutine); .Ve .PP This installs another subroutine in the queue for the specified signal. Subroutines are called in the order that they're added to the queue. Adding a specific subroutine more than once is filtered out so each subroutine in the queue is unique. .PP \&\fBNOTE:\fR Installing handlers for various signals just populates a signal queue with code references. In order for the queue to actuall act upon a signal, however, one must always install the signal dispatcher via \fBinstallSIGD\fR. .SS uninstallSIGH .IX Subsection "uninstallSIGH" .Vb 1 \& uninstallSIGH($signal, &subroutine); .Ve .PP Removes a subroutine from the specified queue. .SS installSIGD .IX Subsection "installSIGD" .Vb 1 \& installSIGD(); .Ve .PP Inserts the dispatcher for each signal with subroutines in the queue. .SS uninstallSIGD .IX Subsection "uninstallSIGD" .Vb 1 \& uninstallSIGD(); .Ve .PP Removes the dispatcher for each signal that's using the dispatcher. The signal handler installed is what ever was set when this module's code was loaded and initialized. .SH DEPENDENCIES .IX Header "DEPENDENCIES" .IP o 4 .IX Item "o" Carp .IP o 4 .IX Item "o" Paranoid .IP o 4 .IX Item "o" Paranoid::Debug .IP o 4 .IX Item "o" POSIX .SH EXAMPLES .IX Header "EXAMPLES" .SS pfork .IX Subsection "pfork" This following example caps the number of children processes to three at a time: .PP .Vb 3 \& $SIG{CHLD} = \e&sigchld; \& MAXCHILDREN = 3; \& for (1 .. 5) { \& \& # Only the children execute the following block \& unless ($pid = pfork()) { \& # .... \& exit 0; \& } \& } .Ve .PP You can also install a child-exit routine to be called by sigchld. For instance, to track the children's history in the parent: .PP .Vb 2 \& 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]\en" }; .Ve .SH "BUGS AND LIMITATIONS" .IX Header "BUGS AND LIMITATIONS" On Solaris \fBpcapture\fR doesn't return a \-1 for non-existant commands, but a 0. On Linux this appears to work as intended. .SH AUTHOR .IX Header "AUTHOR" Arthur Corliss (corliss@digitalmages.com) .SH "LICENSE AND COPYRIGHT" .IX Header "LICENSE AND COPYRIGHT" This software is free software. Similar to Perl, you can redistribute it and/or modify it under the terms of either: .PP .Vb 7 \& a) the GNU General Public License \& as published by the \& Free Software Foundation ; either version 1 \& , or any later version \& , or \& b) the Artistic License 2.0 \& , .Ve .PP subject to the following additional term: No trademark rights to "Paranoid" have been or are conveyed under any of the above licenses. However, "Paranoid" may be used fairly to describe this unmodified software, in good faith, but not as a trademark. .PP (c) 2005 \- 2020, Arthur Corliss (corliss@digitalmages.com) (tm) 2008 \- 2020, Paranoid Inc. (www.paranoid.com)