in reply to get_pidof() messes with wait()?

My guess is that you have one or more logic errors in the program.    I'm also not sure why you're using @ARGV -- is this just to control how many processes get started?  If so, that's okay, but it's a little misleading that you call the loop variable $process.

You may also be expecting that get_pidof is returning the process id only of any running fork.pl programs, but you may have others -- for example, if you're editing fork.pl in the background, then get_pid can match it instead.  So first of all, try passing a second argument to get_pidof:

my @pids = $get_pidof('fork.pl', 1);
which should cause it to find processes which exactly match fork.pl.

Next of all, why are you decrementing $childcnt when the return from the wait is -1?  According to perldoc -f wait:

wait Behaves like the wait(2) system call on your system: it + waits for a child process to terminate and returns the pid of + the deceased process, or "-1" if there are no child process +es. The status is returned in $?. Note that a return value of +"-1" could mean that child processes are being automatically + reaped, as described in perlipc.
Which means you probably want to decrement only when you get a value greater than zero for $completed_pid.  Additionally, you are executing a blocking wait, so the wait will block until it succeeds, or returns -1 for "no more children".  If you want to make it non-blocking, try something like this:
while (1) { my $completed_pid = waitpid(-1, WNOHANG); if ($completed_pid == -1) { # No more children -- exit loop last; } if ($completed_pid > 0) { print "<parent>: $completed_pid is done; $childcnt running\n"; $childcnt--; sleep 1; } }

You'll also need use POSIX ":sys_wait_h"; at the top of the program.  You can read more about non-blocking waits with perldoc -f waitpid.

Update:  I discovered another possible reason why you're getting a negative $childcount when you use get_pidof() ... it's because get_pidof is itself spawning a process which is a child of fork.pl.  This causes your program to wait for it and it decrements $childcount one too many times.


@ARGV=split//,"/:L"; map{print substr crypt($_,ord pop),2,3}qw"PerlyouC READPIPE provides"

Replies are listed 'Best First'.
Re^2: get_pidof() messes with wait()?
by rhumbliner (Sexton) on Apr 18, 2006 at 17:13 UTC
    Your comments got me thinking about how get_pidof() is implemented and therein lies the solution. get_pidof() uses `ps` and kicks off a child process to execute `ps`. So even when my childcnt is zero, wait() will return a proper pid, not -1.

    The solution is to always follow any call to get_pidof() with a call to wait(). That will clear out the pid of the `ps` call.

    Just to touch on your other points:

    1) I use @ARGV just to enumerate the subprocesses I want to kick off. I invoke fork.pl as `fork.pl a b c` to kick off 3 children.

    2) get_pidof() was not picking up the editor running in the background, but it was very astute of you to think of that possibility. That would certainly have wreaked havoc.

    3) The `until` loop only decrements childcnt when the return from wait() is not -1. When wait() returns a -1 the program exits without decrementing childcnt.

    Thanks for your help.