PHP.mk документација

pcntl_wait

Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.

function.pcntl-wait.php PHP.net прокси Преводот се освежува
Оригинал на PHP.net
Патека function.pcntl-wait.php Локална патека за оваа страница.
Извор php.net/manual/en Оригиналниот HTML се реупотребува и локално се стилизира.
Режим Прокси + превод во позадина Кодовите, табелите и белешките остануваат читливи во истиот тек.
pcntl_wait

Референца за `function.pcntl-wait.php` со подобрена типографија и навигација.

function.pcntl-wait.php

pcntl_wait

класата mysqli_driver

pcntl_waitЧека на или го враќа статусот на форкнато дете

= NULL

pcntl_wait(int &$status, int $flags = 0, array &$resource_usage = []): int

The wait function suspends execution of the current process until a child has exited, or until a signal is delivered whose action is to terminate the current process or to call a signal handling function. If a child has already exited by the time of the call (a so-called "zombie" process), the function returns immediately. Any system resources used by the child are freed. Please see your system's wait(2) man page for specific details as to how wait works on your system.

Забелешка:

Функцијата wait го суспендира извршувањето на тековниот процес додека детето не заврши, или додека не се достави сигнал чие дејство е да го прекине тековниот процес или да повика функција за ракување со сигнали. Ако детето веќе завршило во моментот на повикот (т.н. процес „зомби“), функцијата се враќа веднаш. Сите системски ресурси што ги користи детето се ослободуваат. Ве молиме погледнете ја man страницата wait(2) на вашиот систем за специфични детали за тоа како работи wait на вашиот систем. pcntl_waitpid() Оваа функција е еквивалентна на повикување -1 process_id со flags.

Параметри

status

pcntl_wait() што може да се процени со помош на следните функции: status е вредноста на нула или повеќе од следните две глобални константи pcntl_wifexited(), pcntl_wifstopped(), pcntl_wifsignaled(), pcntl_wexitstatus(), pcntl_wtermsig() and pcntl_wstopsig().

flags

и без flags Ако wait3 е достапен на вашиот систем (главно системи во стилот на BSD), можете да го обезбедите опционалниот flags параметар. Ако овој параметар не е обезбеден, ќе се користи wait за системскиот повик. Ако wait3 не е достапен, обезбедувањето вредност за flags нема да има ефект. Вредноста на ORсе враќа веднаш ако ниту едно дете не завршило.

се однесува на низа од вредности на атрибутот релевантни за модификацијата. flags
WNOHANG е вредноста на нула или повеќе од следниве два константи
WUNTRACED Враќање веднаш ако ниту едно дете не завршило.

Вратени вредности

pcntl_wait() Враќање за деца кои се запрени и чиј статус не е пријавен.

Види Исто така

  • pcntl_fork() - Форкира тековно активен процес
  • pcntl_signal() - Инсталира обработувач на сигнали
  • pcntl_wifexited() - Проверува дали кодот за статус претставува нормален излез
  • pcntl_wifstopped() - Проверува дали детето процес е моментално запрено
  • pcntl_wifsignaled() - Проверува дали кодот за статус претставува прекин поради сигнал
  • pcntl_wexitstatus() - Враќа код за враќање на прекинат дете
  • pcntl_wtermsig() - Враќа сигнал што го предизвика прекинот на детето
  • pcntl_wstopsig() - Враќа сигнал што го предизвика запирањето на детето
  • pcntl_waitpid() - Чека или враќа статус на форкирано дете

Белешки од корисници 8 белешки

враќа ID на процесот на детето кое завршило, -1 при грешка или нула ако WNOHANG е обезбеден како опција (на системи со достапен wait3) и ниту едно дете не било достапно.
20 години пред
This a simple multi process application where you can choose 
the maximun process that can run at the same time.
This is useful when you need to limit the fork of process.
When the MAXPROCESS is reached the program wait on pcntl_wait()

<?php

DEFINE(MAXPROCESS,25);

for ($i=0;$i<100;$i++){
    $pid = pcntl_fork();
    
    if ($pid == -1) {
       die("could not fork");
    } elseif ($pid) {
                echo "I'm the Parent $i\n";
        $execute++;
        if ($execute>=MAXPROCESS){
            pcntl_wait($status);
            $execute--;
        }
    } else {
       echo "I am the child, $i pid = $pid \n";
       sleep(rand(1,3));
       echo "Bye Bye from $i\n";        
       exit;
    }
}
?>
federico at nextware dot it
пред 15 години
Using pcntl_fork() can be a little tricky in some situations.  For fast jobs, a child can finish processing before the parent process has executed some code related to the launching of the process.  The parent can receive a signal before it's ready to handle the child process' status.  To handle this scenario, I add an id to a "queue" of processes in the signal handler that need to be cleaned up if the parent process is not yet ready to handle them.

<?php
declare(ticks=1);
//A very basic job daemon that you can extend to your needs.  
class JobDaemon{

    public $maxProcesses = 25;
    protected $jobsStarted = 0; 
    protected $currentJobs = array();
    protected $signalQueue=array();    
    protected $parentPID;
    
    public function __construct(){
        echo "constructed \n";
        $this->parentPID = getmypid();
        pcntl_signal(SIGCHLD, array($this, "childSignalHandler"));
    }
    
    /** 
    * Run the Daemon
    */
    public function run(){
        echo "Running \n";
        for($i=0; $i<10000; $i++){
            $jobID = rand(0,10000000000000);
            $launched = $this->launchJob($jobID);
        }
        
        //Wait for child processes to finish before exiting here
        while(count($this->currentJobs)){
            echo "Waiting for current jobs to finish... \n";
            sleep(1);
        }
    }
    
    /** 
    * Launch a job from the job queue
    */
    protected function launchJob($jobID){
        $pid = pcntl_fork();
        if($pid == -1){
            //Problem launching the job
            error_log('Could not launch new job, exiting');
            return false;
        }
        else if ($pid){
            // Parent process
            // Sometimes you can receive a signal to the childSignalHandler function before this code executes if 
            // the child script executes quickly enough!
            //
            $this->currentJobs[$pid] = $jobID;
            
            // In the event that a signal for this pid was caught before we get here, it will be in our signalQueue array
            // So let's go ahead and process it now as if we'd just received the signal
            if(isset($this->signalQueue[$pid])){
                echo "found $pid in the signal queue, processing it now \n";
                $this->childSignalHandler(SIGCHLD, $pid, $this->signalQueue[$pid]);
                unset($this->signalQueue[$pid]);
            }
        }
        else{
            //Forked child, do your deeds.... 
            $exitStatus = 0; //Error code if you need to or whatever
            echo "Doing something fun in pid ".getmypid()."\n";
            exit($exitStatus);
        }
        return true;
    }
    
    public function childSignalHandler($signo, $pid=null, $status=null){
        
        //If no pid is provided, that means we're getting the signal from the system.  Let's figure out
        //which child process ended
        if(!$pid){
            $pid = pcntl_waitpid(-1, $status, WNOHANG);
        }
        
        //Make sure we get all of the exited children
        while($pid > 0){
            if($pid && isset($this->currentJobs[$pid])){
                $exitCode = pcntl_wexitstatus($status);
                if($exitCode != 0){
                    echo "$pid exited with status ".$exitCode."\n";
                }
                unset($this->currentJobs[$pid]);
            }
            else if($pid){
                //Oh no, our job has finished before this parent process could even note that it had been launched!
                //Let's make note of it and handle it when the parent process is ready for it
                echo "..... Adding $pid to the signal queue ..... \n";
                $this->signalQueue[$pid] = $status;
            }
            $pid = pcntl_waitpid(-1, $status, WNOHANG);
        }
        return true;
    }
}
duerra at yahoo dot com
пред 15 години
pcntl_wait will not terminate on signals if you have a PHP signal handler activated (pcntl_signal).
This is unless the signal handler was activated with 3rd parameter=true.

Example:
<?php
declare(ticks=1);
pcntl_signal(SIGTERM, "myHandler");
$pid=pcntl_wait($status);
?>

This will not terminate on SIGTERM sent to the process, because "wait" will be restarted after php recieves the signal. The signal handler "myHandler" will not be called unless pcntl_wait terminates for some other reason.

Change to:
<?php
declare(ticks=1);
pcntl_signal(SIGTERM, "myHandler", true);
$pid=pcntl_wait($status);
?>

Now the pcntl_wait terminates when a signal comes in and "myHandler" will be called on SIGTERM. (Make sure to put the wait in a loop though, because it will now not only terminate when a child exits but also when a signal arrives. Test for $pid>0 to detect a exit message from a child)
(thanks to Andrey for helping me debugging this)
gaylord at 100days dot de
Nimja
If pcntl_wait() hangs and doesn't detect that the child process has exited, you must check if your PHP has the gRPC PECL extension installed. gRPC brake pcntl_wait() checked on all PHP versions from 7.0 to 8.4. And gRPC 1.72.0.
federico at nextware dot it
пред 15 години
Oops, I stripped just a little much from the job daemon code in the previous comment.  You'll want to add a little line before the ->launchJob() method is called:

<?php

while(count($this->currentJobs) >= $this->maxProcesses){
    echo "Maximum children allowed, waiting...\n";
    sleep(1); 
}
digitalaudiorock на gmail точка com
пред 15 години
I was unable to get pcntl_wait or pcntl_waitpid to terminate when I had an active signal handler.  I then noticed the post below from gaylord at 100days dot de, however I'm a little confused by that post as I found the exact opposite to be true.  The default value of the third parameter of pcntl_signal (the restart_syscalls parameter) is true and this seems to cause the wait to continue when the signal arrives.  In order to prevent this I had to expressly set it to false.  That is:

pcntl_signal(SIGTERM, 'my_handler_function', false);
rudenko at ukraine dot com dot ua
20 години пред
Below is a simple example of forking some children and timing the total duration (useful for stress tests).

<?php

$isParent    = true;
$children    = array();
$start        = microtime( true);

/* Fork you!
 * (Sorry, I had to)
 */
$ceiling = $CONCURRENCY - 1;

for ( $i = 0; (( $i < $ceiling) && ( $isParent)); $i++) {
    $pid = pcntl_fork();
    if ( $pid === 0) {
        $isParent = false;
        
    } elseif ( $pid != -1) {
        $children[] = $pid;
        
    }

}

/* Process body */
echo "Do stuff here\n";

/* Cleanup */
if ( $isParent) {
    $status = null;
    while ( count( $children)) {
        pcntl_wait( $status);
        array_pop( $children);
    }
    
    echo "Completed in " . ( microtime( true) - $start) . " seconds.\n";
    
}

?>
thisisroot at gmail dot com
20 години пред
The code before isnt working for me cause the children are correctly started but not refreshed after they died. So keep in mind to use this instead and use the signal handler to know when a child exits to know when you have to start a new one. I added a few lines to the posting from {andy at cbeyond dot net} cause his post wasnt working for me as well (PHP5.1). Same effect like the one below.

<?php
declare(ticks = 1);

$max=5;
$child=0;

// function for signal handler
function sig_handler($signo) {
  global $child;
  switch ($signo) {
   case SIGCHLD:
     echo "SIGCHLD received\n";
     $child--;
  }
}

// install signal handler for dead kids
pcntl_signal(SIGCHLD, "sig_handler");

while (1){
       $child++;
       $pid=pcntl_fork();
       
       if ($pid == -1) {
               die("could not fork");
       } else if ($pid) {
               
               // we are the parent
               if ( $child >= $max ){
                   pcntl_wait($status);
                   $child++;
               }
       } else {
               // we are the child
               echo "\t Starting new child | now we de have $child child processes\n";
               // presumably doing something interesting
               sleep(rand(3,5));
               exit;
       }
}
?>
На оваа страница

Автоматски outline од активната документација.

Насловите ќе се појават тука по вчитување.

Попрегледно читање

Примерите, changelog табелите и user notes се визуелно издвоени за да не се губат во долгата содржина.

Брз совет Користи го outline-от Скокни директно на главните секции од активната страница.
Извор Оригиналниот линк останува достапен Кога ти треба целосен upstream context, отвори го PHP.net во нов tab.