On further investigation I have made my cli script below behave as expected. However when calling this using exec or proc_open a result is not returned till all the children end. Is there a way to get exec not to wait for the children processes?
<?php
$suppliers=array
(
'HC',
'GT',
'HT'
);
$SearchCriteria=1;
//set timeout to 8s
$timeout =8;
$count =0;
$pidarray=array();
searchSupplier($suppliers, $SearchCriteria);
//if in parent watch for children
while (count($pidarray) && $count < $timeout)
{
foreach ($pidarray as $key => $p)
{
echo getmypid() . " loop $count Checking child $p \n";
if (!is_process_running($p))
{
unset($pidarray[$key]);
}
sleep(1);
$count++;
}
}
if (count($pidarray))
{
echo "Exit due to timeout\n";
exit(2);
}
else
{
echo "Success\n";
exit(1);
}
function searchSupplier($suppliers, $SearchCriteria)
{
global $pidarray;
if ($supplierCode=array_shift($suppliers))
{
$pId=pcntl_fork();
if ($pId == -1)
{
die("Forking Failed!");
}
else if ($pId)
{
searchSupplier($suppliers, $SearchCriteria);
$PID =getmypid();
$pidarray[]=$pId;
}
else
{
echo '[' . getmypid() . '] Supplier (' . $supplierCode . ') search initiated' . "\n";
//simulate random response times
sleep(rand(1, 20));
echo "$supplierCode " . getmypid() . " done\n";
exit(1);
}
}
}
function is_process_running($PID)
{
//check if process is running and not zombie
exec("ps $PID | grep -v Z", $ProcessState);
if (count($ProcessState) >= 2)
{
return true;
}
else
{
//remove zombie children
pcntl_waitpid($PID, $status);
return false;
}
}
?>