roadrunner has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I'm trying to find the most processor-efficient way of writing some code to do the following:

someLoop { ... ... do stuff ... ... if(I *don't* have one and only one child proc running) { launch asynchronous child process } ... ... carry on doing stuff while child runs ... ... }

I've played around a bit with fork(), but:

(a) Do not know whether it is the most efficient and stable way of doing this.
(b) Do not have enough Perl experience to be able to ensure I only ever have JUST ONE child running at any time. I only seem to be able to fork multiple processes.

Any advice, particularly code examples, would be appreciated...especially for how I can do the check in the if statement.

Thanks,
Roadrunner.

Replies are listed 'Best First'.
Re: How to fork one and only one child process from a loop ?
by idsfa (Vicar) on Mar 18, 2006 at 04:50 UTC

    This skeleton has no error checking, but it does only spawn one child.

    my $kidpid; while( ... loop condition ... ) { . . . if( ! $kidpid) { if(0 == ($kidpid=fork())) { # I'm the child exec { ... } die("How did I get here?"); } } # I'm the parent, keep doing stuff . . . # Before I loop, do a lame check to make sure kid # is still running. Ought to use a Proc:: Module $kidpid=0 if(! grep { m/^\s+$kidpid\s/ } `ps ax`); }

    The intelligent reader will judge for himself. Without examining the facts fully and fairly, there is no way of knowing whether vox populi is really vox dei, or merely vox asinorum. — Cyrus H. Gordon
Re: How to fork one and only one child process from a loop ?
by graff (Chancellor) on Mar 18, 2006 at 23:12 UTC
    To handle the bit about checking whether an existing child process is still running, you'd want to use the waitpid function -- that is, if your system is one that supports the POSIX "WNO_HANG" flag for doing a non-blocking check as to whether a child process is still running.

    In that case, once waitpid returns a status value that indicates the child process is finished, you can reset the $kidpid value to zero, so that your loop can launch another child if it wants to.

Re: How to fork one and only one child process from a loop ?
by salva (Canon) on Mar 19, 2006 at 18:06 UTC
    use Proc::Queue size => 1, ignore_childs => 1, qw(running_now); someLoop { ... ... do stuff ... ... if(running_now < 1) { my $pid = fork; defined $pid or die ... unless ($pid) { ... do stuff in child ... exit(0); } } ... ... carry on doing stuff while child runs ... ... }