PHP - Infinity loop with pcntl_fork - php

I need to write code which meets few conditions:
Is an infinity loop
After 4 forks, goes to sleep for 5 seconds.
When in child process, execute things.
When in parent process, fork again.
When it returns -1, catch exception.
So here's what I've written so far:
while(true) {
for ($i = 1; $i <= 4; ++$i) {
$pid = pcntl_fork();
if($pid == 0){
//execute stuff
} else if ($pid == -1){
//error
} else if($pid > 0) {
//fork again?
}
}
sleep(5);
}
But I feel like this is just plain wrong. Also I have no idea how to fork again in parent. How this should look like?

Related

Symfony Tasks wait for multiple tasks

I'm starting 10 processes asynchronously:
$procs = [];
for($i = 0; $i < 10; $i++) {
$proc = new Process('ls -lsa');
$proc->start();
$procs[$i] = $proc;
}
Now i want to wait asynchronous for every process to finish and print out state informations while waiting:
foreach($procs as $proc) {
$proc->wait(function ($type, $buffer) {
if (Process::ERR === $type) {
// Print out error ...
} else {
// Print out state informations ...
});
}
}
The Problem is at the wait function. It waits for the task to finish and then go on to the next tasks. But i want this to run asynchronous.
How can i do this?
Thanks !
As per the Symfony docs the wait method is blocking and therefore will wait until that process is finished before continuing.
If you don't want to wait you could refactor your code to use the run method:
for($i = 0; $i < 10; $i++) {
$process = new Process('ls -lsa');
$process->run(function ($type, $buffer) {
if (Process::ERR === $type) {
echo 'ERR > '.$buffer;
} else {
echo 'OUT > '.$buffer;
}
});
$procs[$i] = $proc;
}

how to start a terminated child process from parent in php

I am trying to start a child process from parent when its terminated normally or due to an error.Using pcntl_waitpid, It become possible to get status from child. By that status I want restart the same script or process again. Here is an example.
<?php
for ($i = 1; $i <= 5; ++$i) {
$pid = pcntl_fork();
if (!$pid) {
sleep(1);
print "In child $i\n";
exit($i);
}
}
while (pcntl_waitpid(0, $status) != -1) {
$status = pcntl_wexitstatus($status);
echo "Child $status completed\n";
}
?>
How can it possible? Thanks in advance.
Try
echo $i;
break;
instead
exit($i);

How to start and end new php procces?

I am trying to use a pcntl extetntion for PHP to run some methods of my CLI class in a new thread. I wrote a small test method:
private function startProcess($data)
{
$this->log('Start a child process');
$pid = pcntl_fork();
if($pid == -1)
$this->log('Could not fork');
elseif($pid)
pcntl_wait($status);
else {
$this->process($data);
sleep(10);
posix_kill(posix_setsid(), SIGTERM);
}
}
This method is called 10 times. $this->process($data); just prints the data in the console. As i understood it should start 10 processes and print my data, after it exit. But instead i get to wait 10 seconds for each message. Where i'm wrong?
You are waiting for each process to complete immediately after starting it. If you really want to run 10 at a time, don't wait until you started all 10.
for($i = 0; $i < 10; $i++)
startProcess(...);
for($i = 0; $i < 10; $i++)
pcntl_wait($status);
private function startProcess($data)
{
$this->log('Start a child process');
$pid = pcntl_fork();
if($pid == -1)
$this->log('Could not fork');
elseif(!$pid) {
$this->process($data);
sleep(10);
posix_kill(posix_setsid(), SIGTERM);
}
}

Limiting XML read to 5 records

I have a xml file with 100 records, but I want it to limit it to just 5 records
for ($i=0;$i<=5;$i++) {
foreach($xml->entry as $result){
if ($result->updated == $result->published) {
}
}
}
When I put in the above code, it display one record 5 times.
Thanks
Jean
$count = 0;
foreach($xml->entry as $result)
{
if ($result->updated == $result->published) {
}
$count++;
if ($count++ == 5) break;
// if ($count++ == 5) break; think this might work aswell
}
It seems that the foreach loop runs only once, because there is only one entry, and the for loop prints it 5 times. If there were more than one, this code would print each entry 5 times. If $xml->entry is an array, you can do it like this:
for($i = 0; $i < 5; $i++) {
$result = $xml->entry[$i];
if($result->updated == $result->published) {
}
}
Check if there are more than one <entry> tags in your XML file.

how to change the while loop condition depending on stuff?

by this question what i mean is that if, by example, someone's username is "bob" then the while loop condition will be ($i < 10), and if the username is something else then the while loop condition will be ($i > 10)
if($username == "bob")
{
//make this while loop condition: ($i < 10)
// it means: while($i <10){ so stuff}
}
else
{
//make the while loop condition: ($i >10)
}
Make do_stuff a function, then this is perfectly readable (although special-casing 'bob' seems doubtable at best).
if($username == "bob")
{
while($i<10) {
do_stuff();
}
}
else
{
while($i>10) {
do_stuff();
}
}
while( ($username == 'bob' && $i <10 ) XOR $i > 10){}
$username == 'bob' will be evaluated first if it comes out to be true then $i < 10 is evaluated.
$var1 XOR $var2 is true only when one of $var1, $var2 is true but not both.
But I myself will go with this.
Try making two different while loops within the if and else blocks.
Is this what you mean? You can just take a different path depending on the success or failure of the if. If the code inside is the same, just call a method to avoid duplicating it.
if($username == "bob")
{
//make this while loop condition: ($i < 10)
// it means: while($i <10){ so stuff}
while ($i < 10) {
call_method();
}
}
else
{
while ($i > 10) {
call_method();
}
}
To keep your code simple:
if($username == "bob")
{
while ($i<10){
}
}
else
{
while ($i>10){
}
}
There are other better ways to handle it but they may make your code difficult to understand like using eval which I dont like.

Categories