Jump to content

Move a child fork to a background process


bensono

Recommended Posts

I have an application that aggregates data from various suppliers.

 

The user enters the criteria on a page the php script running under apache uses proc_open to call a php cli script.

The cli script forks for each supplier and gets the content.

 

Once all children have completed (i am using  pcntl_wait()) the search gets marked as completed and the results are returned to the browser.

 

The above all works well most of the time. However dependant on the request certain suppliers may take much longer to return the data then others. This can sometimes be upto 4 minutes.

 

What I want to do is set the cli script to become a background process if it takes longer than 60s. The search would be marked as partially completed and return control to the apache php process to return the partial result set.

 

Once the background cli script has completed the search would be marked as completed. I can then make an ajax call from the client to poll every 10s to check if the search is completed and when complete refresh the results.

 

Is it possible to make the cli script a background process if it takes longer than a certain amount of time to process? How would would i go about achieving this.

 

Thanks for your help.

Is it possible to make the cli script a background process if it takes longer than a certain amount of time to process? How would would i go about achieving this.

 

No. You would either need to background it from the start or not.

 

Your question is OS related, not really php.

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;
        }
    }
?>

 

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.