The issue you are encountering is that waitpid ($pid,0) is a blocking call. This means that the conditional on your until loop doesn't finish executing until your child has actually returned. You can perform a non-blocking call on systems that support it using:
use POSIX ":sys_wait_h";
#...
do {
$kid = waitpid(-1, WNOHANG);
} while $kid > 0;
where the above is copied from waitpid. Note that not all systems support non-blocking calls to waitpid. See also perlipc. | [reply] [d/l] [select] |
| [reply] |
In my experience, it is better for the parent process to be, basically, a supervisor, not “an active player in the game.”
In other words, in your scenario I would have two child processes: the one that you describe, and a second one to “perform some action.” The parent, then, sits in a wait-state, biding its time until one of the two of them finishes their task. The child processes, having signaled their parent, then enter a wait-state asking for further instructions. (Queues are a great way to handle this sort of thing.)
If the “perform some action” action needs to be suspended when the first process has completed its work, then of course the parent could signal that child to do so. But it may well be that the work of the second process could continue, perhaps at a much lower execution priority. The operating system could be relied-upon to fairly distribute the available CPU(s) time among the three of them, giving you a very flexible and robust arrangement.
It is also frequently useful to devise a queue-based mechanism (hint: there are many CPAN modules already out there for this...) which would allow you to express things like “download a file” as “create a ‘download a file’ request and place it on such-and-such a queue.” This queue is then serviced by a pool of n “worker bee” processes or threads, all under the supervision of a parent. The workload-level that the CPU(s) undertake is strictly governed by the size of that worker-bee pool. (The queue, on the other hand, can become as large as it likes... or not... your option.)
Again: “do not do a thing already done!” This is “a legendary architecture,” and there is plenty of well-rounded CPAN support for it.
| |
Do you know what that next; is doing? Nothing. It's exiting a block you'd be exiting anyway.
As for the loop waiting for waitpid to return something other than 0, my first guess is, since "doesn't work" is kind of vague, that it seems to you the loop never runs?
Update:Yeah, what kennethk said abut it being a blocking call. I didn't even think of that for some reason. I'm going to blame lack of sleep. That explains the same loop-never-seems-to-run behavior but for the correct reason. I'll put my bad guess in a readmore. That's easier to read than a strikethrough.
If you're having some other version of "doesn't work", then more detail may be helpful.
| [reply] [d/l] |
maybe you should look into threads?
use threads;
my $thr = async{ &download_a_file(); };
&calculate_network_bandwidth() while($thr->is_running());
$thr->join();
but you might need use threads::shared if there are any shared variables.
| [reply] [d/l] |
When I first looked at your question, I couldn't see the problem, you wanted to start something
then wait "until" it was done (waitpid). Ok, er, oh...you want to some code to execute
while you are in the wait call?
Er, um you'll need to have someone else do that cuz, you just told it to wait until it's done.
(or, like others have said, 1) waitpid is 'blocking' ....(that's what you wanted? No? Ooops...),
so either use non-blocking form of waitpid OR have something else (process/thread) do the
calculate loop. Depends on what the calc routine does and how it interacts with the existing program
variables as to whether or not threads or a process would be better.
If you use the non-waiting form of 'waitpid', be sure to read the 'perlipc' manpage to get the right
example to guard against "gotcha's", like signals dropping between the cracks.
Basically you have to use 'waitpid' IN a child process you setup before you fork. Examples are in the manpage.
| [reply] |