コード例 #1
1
 /** @return bool did a child exit? */
 private function cleanChildren()
 {
     $status = null;
     if ($exited = pcntl_wait($status, WNOHANG)) {
         unset($this->workerProcesses[$exited]);
         $this->getLogger()->info("Worker {$exited} got WNOHANG during normal operation");
         return true;
     }
     return false;
 }
コード例 #2
1
function wait()
{
    global $fatherpid;
    if (posix_getpid() == $fatherpid) {
        tlog("begin wait");
        while (($pid = pcntl_wait($stat)) > 0) {
            tlog("child." . $pid . ". terminated \n");
        }
    }
}
コード例 #3
0
ファイル: Manager.php プロジェクト: jarnix/nofussframework
 public function run()
 {
     $this->numberOfThreadsToLaunch = $this->numberOfTasks;
     if ($this->maxThreads == 0 || count($this->pool) <= $this->maxThreads) {
         $this->launchAllTasks();
     } else {
         while ($this->numberOfRunningThreads < $this->maxThreads) {
             $this->launchNextTask();
         }
     }
     while (1) {
         // echo "waiting\n";
         $pid = pcntl_wait($extra);
         if ($pid == -1) {
             break;
         }
         // echo ": task done : $pid\n";
         $this->finishTask($pid);
         if ($this->numberOfThreadsToLaunch) {
             $this->launchNextTask();
         }
     }
     // echo "processes done ; exiting\n";
     return;
 }
コード例 #4
0
ファイル: main.php プロジェクト: seiran1944/slate
 /**
  * Create a daemon process.
  *
  * @return  DaemonHttpApplication  Return self to support chaining.
  */
 public function execute()
 {
     // Create first child.
     if (pcntl_fork()) {
         // I'm the parent
         // Protect against Zombie children
         pcntl_wait($status);
         exit;
     }
     // Make first child as session leader.
     posix_setsid();
     // Create second child.
     $pid = pcntl_fork();
     if ($pid) {
         // If pid not 0, means this process is parent, close it.
         $this->processId = $pid;
         $this->storeProcessId();
         exit;
     }
     $this->addLog('Daemonized');
     fwrite(STDOUT, "Daemon Start\n-----------------------------------------\n");
     $this->registerSignalHandler();
     // Declare ticks to start signal monitoring. When you declare ticks, PCNTL will monitor
     // incoming signals after each tick and call the relevant signal handler automatically.
     declare (ticks=1);
     while (true) {
         $this->doExecute();
         sleep(1);
     }
     return $this;
 }
コード例 #5
0
ファイル: Process.php プロジェクト: xxlixin1993/spider
 /**
  * 多进程处理任务
  * @param callback  $mission_func 子进程要进行的任务函数
  */
 public function dealMission($mission_func)
 {
     $this->_mission_func = $mission_func;
     for ($i = 0; $i < $this->_process_num; $i++) {
         $pid[] = pcntl_fork();
         if ($pid[$i] == 0) {
             //等于0时,是子进程
             $this->_func_obj->{$mission_func}($i + 1);
             //结束当前子进程,以防止生成僵尸进程
             if (function_exists("posix_kill")) {
                 posix_kill(getmypid(), SIGTERM);
             } else {
                 system('kill -9' . getmypid());
             }
             exit;
         } else {
             if ($pid > 0) {
                 //大于0时,是父进程,并且pid是产生的子进程的PID
                 //TODO 可以记录下子进程的pid,用pcntl_wait_pid()去等待程序并结束
                 pcntl_wait($status);
             } else {
                 throw new Exception('fork fail');
             }
         }
     }
 }
コード例 #6
0
ファイル: Monitor.php プロジェクト: pmvc-plugin/supervisor
 public function __construct(callable $callBack = null)
 {
     $plug = \PMVC\plug(PLUGIN);
     $plug->log("Monitor starting.");
     while (empty($plug[IS_STOP_ALL]) || count($plug[CHILDREN])) {
         if (!empty($plug[MY_PARENT])) {
             break;
         }
         // Check for exited children
         $pid = pcntl_wait($status, WNOHANG);
         if (isset($plug[CHILDREN][$pid])) {
             $exitCode = pcntl_wexitstatus($status);
             $plug->log("Child {$pid} was stopped with exit code of {$exitCode}");
             if (!$plug[IS_STOP_ALL] && 1 !== $exitCode) {
                 $callbackId = $plug[CHILDREN][$pid];
                 $plug['start']->restore($callbackId);
             }
             $plug->cleanPid($pid);
         }
         pcntl_signal_dispatch();
         if (empty($plug[CHILDREN])) {
             $plug[IS_STOP_ALL] = true;
             break;
         }
         if ($callBack && empty($plug[IS_STOP_ALL])) {
             call_user_func($callBack);
         }
         // php will eat up your cpu if you don't have this
         usleep(50000);
         pcntl_signal_dispatch();
     }
     $plug->log("Monitor was exited.");
 }
コード例 #7
0
 /**
  * Start the task manager
  *
  * @param AbstractTask $task Task to start
  *
  * @return void
  */
 public function start(AbstractTask $task)
 {
     $pid = pcntl_fork();
     if ($pid == -1) {
         throw new \Exception('[Pid:' . getmypid() . '] Could not fork process');
     } elseif ($pid) {
         $this->_activeThreads[$pid] = true;
         // Reached maximum number of threads allowed
         if ($this->maxThreads == count($this->_activeThreads)) {
             // Parent Process : Checking all children have ended (to avoid zombie / defunct threads)
             while (!empty($this->_activeThreads)) {
                 $endedPid = pcntl_wait($status);
                 if (-1 == $endedPid) {
                     $this->_activeThreads = array();
                 }
                 unset($this->_activeThreads[$endedPid]);
             }
         }
     } else {
         $task->initialize();
         // On success
         if ($task->process()) {
             $task->onSuccess();
         } else {
             $task->onFailure();
         }
         posix_kill(getmypid(), 9);
     }
     pcntl_wait($status, WNOHANG);
 }
コード例 #8
0
 public function run()
 {
     $count = 0;
     $socket = stream_socket_server($this->socketString, &$errno, &$errstr);
     if (!$socket) {
         throw new RuntimeException($errstr);
     }
     while (true) {
         while (count($this->children) < $this->maxConnections) {
             $count++;
             $pid = pcntl_fork();
             if ($pid == -1) {
                 throw new RuntimeException('Couldn\'t fork');
             } elseif ($pid == 0) {
                 $this->createChild($socket, $count);
                 exit;
             }
             $this->children[] = $pid;
         }
         while (pcntl_wait($status, WNOHANG or WUNTRACED) > 0) {
             usleep(500000);
         }
         while (list($key, $val) = each($this->children)) {
             if (!posix_kill($val, 0)) {
                 unset($this->children[$key]);
             }
         }
         $this->children = array_values($this->children);
         usleep(500000);
     }
 }
コード例 #9
0
 protected function _doTestStartAll($baseConfig, $useFactoryMethodToCreateKeeper = false)
 {
     $config = $baseConfig;
     $config['quantity'] = $quantity = 3;
     if (!$useFactoryMethodToCreateKeeper) {
         $keeper = new OneForOneKeeper(array(new Config($config)));
     } else {
         $keeper = \Comos\Qpm\Supervision\Supervisor::oneForOne($config)->getKeeper();
     }
     $keeper->startAll();
     $pids = array();
     for ($i = 0; $i < $quantity; $i++) {
         $status = 0;
         $pids[\pcntl_wait($status)] = true;
     }
     $currentPid = \posix_getpid();
     $r = \file_get_contents($this->_logFile);
     $lines = explode("\n", $r);
     $count = 0;
     foreach ($lines as $line) {
         if (trim($line)) {
             list($pid, $ppid) = explode(',', $line);
             $count++;
             $this->assertTrue($pids[$pid]);
             $this->assertEquals($currentPid, $ppid);
         }
     }
     $this->assertEquals($quantity, $count);
 }
コード例 #10
0
ファイル: executor.php プロジェクト: adispartadev/njq
 /**
  * Run jobs
  *
  * Run all jobs provided by the job provider.
  *
  * Jobs are run parallel in the background. The number of jobs executed in 
  * parallel can be specified as the second parameter.
  *
  * Returns once all jobs have been executed.
  * 
  * @param JobProvider $jobs 
  * @param int $parallel 
  * @return void
  */
 public function run(JobProvider $jobs, $parallel = 4)
 {
     $this->logger->startExecutor($this, $jobs);
     $forks = array();
     $jobNr = 0;
     while ($jobs->hasJobs() || count($forks)) {
         while (count($forks) < $parallel && ($job = $jobs->getNextJob())) {
             $this->logger->progressJob(++$jobNr);
             if (($forks[] = pcntl_fork()) === 0) {
                 // We are the newly forked child, just execute the job
                 call_user_func($job);
                 exit(0);
             }
         }
         do {
             // Check if the registered jobs are still alive
             if ($pid = pcntl_wait($status)) {
                 // Job has finished
                 $jobId = array_search($pid, $forks);
                 unset($forks[$jobId]);
             }
         } while (count($forks) >= $parallel);
     }
     $this->logger->finishedExecutor();
 }
コード例 #11
0
 /**
  * Signals handler function
  *
  * @param integer $signal
  * @final 
  */
 public final function HandleSignals($signal)
 {
     $this->Logger->debug("HandleSignals received signal {$signal}");
     if ($signal == SIGUSR2) {
         $this->Logger->debug("Recived SIGUSR2 from one of childs");
         $this->ProcessManager->PIDs = array();
         $this->ProcessManager->ForkThreads();
         return;
     }
     $pid = @pcntl_wait($status, WNOHANG | WUNTRACED);
     if ($pid > 0) {
         $this->Logger->debug("Application received signal {$signal} from child with PID# {$pid} (Exit code: {$status})");
         foreach ((array) $this->ProcessManager->PIDs as $ipid => $ipid_info) {
             if ($ipid == $pid) {
                 unset($this->ProcessManager->PIDs[$ipid]);
                 if ($this->ProcessManager->PIDDir) {
                     $this->Logger->debug("Delete thread PID file {$ipid}");
                     @unlink($this->ProcessManager->PIDDir . "/" . $ipid);
                 }
                 $known_child = true;
                 break;
             }
         }
         if ($known_child) {
             $this->ProcessManager->ForkThreads();
         } else {
             $this->Logger->debug("Signal received from unknown child.");
         }
     }
 }
コード例 #12
0
ファイル: crond.php プロジェクト: sdgdsffdsfff/xcron
 public function start($daemon = false)
 {
     /*{{{*/
     if ($daemon) {
         if (!$this->daemonize()) {
             return false;
         }
     }
     $this->master_process_id = posix_getpid();
     $this->startServer();
     $this->startAgent();
     while (true) {
         $pid = pcntl_wait($status, WNOHANG);
         switch ($pid) {
             case $this->listen_process_id:
                 CronLogger::err("Cron server not running[{$status}], starting ...");
                 $this->startServer();
                 CronLogger::err("Cron server restart done.");
                 break;
             case $this->agent_process_id:
                 CronLogger::err("Cron agent not running[{$status}], starting ...");
                 $this->startAgent();
                 CronLogger::err("Cron server restart done.");
                 break;
             case -1:
                 posix_kill($this->listen_process_id, 9);
                 posix_kill($this->agent_process_id, 9);
                 $this->startAgent();
                 $this->startServer();
                 break;
         }
         sleep(3);
     }
 }
コード例 #13
0
 public function go()
 {
     foreach ($this->servers as $server) {
         $handler = new Handler\Daemonic($server['socket'], $server['protocol'], $server['transport']);
         // drop privileges after opening sockets, but before entering the working loop
         // this will only work when the process is started by root
         $this->dropPrivileges($server);
         for ($i = 0; $i < $server['min-children']; $i++) {
             $this->startWorker($handler, $server['app']);
         }
     }
     while (true) {
         pcntl_signal(SIGTERM, array($this, 'sigterm'), false);
         pcntl_signal(SIGINT, array($this, 'sigterm'), false);
         pcntl_signal(SIGHUP, array($this, 'sighup'), false);
         $status = null;
         declare (ticks=1) {
             $old_pid = pcntl_wait($status);
         }
         if (0 === $old_pid) {
             echo "[no workers]\n";
             return;
         }
         if (-1 === $old_pid) {
             continue;
             // signal arrived
         }
         echo "[Restarting Worker]\n";
         pcntl_signal(SIGTERM, SIG_DFL);
         pcntl_signal(SIGINT, SIG_DFL);
         pcntl_signal(SIGHUP, SIG_DFL);
         $this->restartWorker($old_pid);
     }
 }
コード例 #14
0
       /**
        * Signals handler function
        *
        * @param integer $signal
        * @final 
        */
       final public function HandleSignals($signal)
       {
           //Log::Log("HandleSignals received signal {$signal}", E_NOTICE);            
           $pid = @pcntl_wait($status, WNOHANG | WUNTRACED);
           
           if ($pid > 0)
   		{
   		    //Log::Log("Application received signal {$signal} from child with PID# {$pid} (Exit code: {$status})", E_NOTICE);
 
   		    foreach((array)$this->ProcessManager->PIDs as $kk=>$vv)
   			{
   				if ($vv == $pid)
   				{
   					unset($this->ProcessManager->PIDs[$kk]);
   					$known_child = true;
   					break;
   				}
   			}
   			
   			if ($known_child)
   				$this->ProcessManager->ForkThreads();
   			else
   			{
   				//Log::Log("Signal received from unknown child.", E_NOTICE);
   			}
   		}
       }
コード例 #15
0
ファイル: ForkController.php プロジェクト: ruizrube/spdef
 /**
  * Start the child processes. 
  *
  * This should only be called from the command line. It should be called 
  * as early as possible during execution.
  *
  * This will return 'child' in the child processes. In the parent process, 
  * it will run until all the child processes exit or a TERM signal is 
  * received. It will then return 'done'.
  */
 public function start()
 {
     // Trap SIGTERM
     pcntl_signal(SIGTERM, array($this, 'handleTermSignal'), false);
     do {
         // Start child processes
         if ($this->procsToStart) {
             if ($this->forkWorkers($this->procsToStart) == 'child') {
                 return 'child';
             }
             $this->procsToStart = 0;
         }
         // Check child status
         $status = false;
         $deadPid = pcntl_wait($status);
         if ($deadPid > 0) {
             // Respond to child process termination
             unset($this->children[$deadPid]);
             if ($this->flags & self::RESTART_ON_ERROR) {
                 if (pcntl_wifsignaled($status)) {
                     // Restart if the signal was abnormal termination
                     // Don't restart if it was deliberately killed
                     $signal = pcntl_wtermsig($status);
                     if (in_array($signal, self::$restartableSignals)) {
                         echo "Worker exited with signal {$signal}, restarting\n";
                         $this->procsToStart++;
                     }
                 } elseif (pcntl_wifexited($status)) {
                     // Restart on non-zero exit status
                     $exitStatus = pcntl_wexitstatus($status);
                     if ($exitStatus > 0) {
                         echo "Worker exited with status {$exitStatus}, restarting\n";
                         $this->procsToStart++;
                     }
                 }
             }
             // Throttle restarts
             if ($this->procsToStart) {
                 usleep(500000);
             }
         }
         // Run signal handlers
         if (function_exists('pcntl_signal_dispatch')) {
             pcntl_signal_dispatch();
         } else {
             declare (ticks=1) {
                 $status = $status;
             }
         }
         // Respond to TERM signal
         if ($this->termReceived) {
             foreach ($this->children as $childPid => $unused) {
                 posix_kill($childPid, SIGTERM);
             }
             $this->termReceived = false;
         }
     } while (count($this->children));
     pcntl_signal(SIGTERM, SIG_DFL);
     return 'done';
 }
コード例 #16
0
 public function go()
 {
     $is_parent = true;
     foreach ($this->servers as $server) {
         $app = new $server[0]();
         foreach (array_reverse($server[1]) as $mw_name) {
             $mw_class = 'MFS\\AppServer\\Middleware\\' . $mw_name . '\\' . $mw_name;
             $app = new $mw_class($app);
         }
         $handler = new \MFS\AppServer\DaemonicHandler($server[3], $server[2], 'Socket');
         for ($i = 0; $i < $server[4]; $i++) {
             $pid = pcntl_fork();
             if ($pid == -1) {
                 die('could not fork');
             } elseif ($pid === 0) {
                 // we are the child
                 $is_parent = false;
                 try {
                     $handler->serve($app);
                 } catch (\Exception $e) {
                 }
                 die;
             } else {
                 // parent-process, just continue
             }
         }
     }
     if ($is_parent) {
         // should be called one time for each child?
         pcntl_wait($status);
         //Protect against Zombie children
     }
 }
コード例 #17
0
 public function start()
 {
     $pid = pcntl_fork();
     if ($pid < 0) {
         throw new Exception('count not fork');
     } elseif ($pid == 0) {
         //parent
         if (empty($this->producer)) {
             exit;
         }
         $cur_size = 0;
         while (true) {
             $pid = pcntl_fork();
             if ($pid == -1) {
                 die("could not fork");
             } else {
                 if ($pid) {
                     // parent
                     $cur_size++;
                     if ($cur_size >= $this->work_count) {
                         $sunPid = pcntl_wait($status);
                         $cur_size--;
                     }
                 } else {
                     // worker
                     exit;
                 }
             }
         }
     } else {
         //sun parent
     }
 }
コード例 #18
0
ファイル: Worker.php プロジェクト: cobolbaby/workman
 public function work()
 {
     //echo "Worker started with pid $this->pid...\n";
     if ($this->daemonize) {
         $pid = pcntl_fork();
         if ($pid == 0) {
             $this->pid = getmypid();
             $this->isDaemon = true;
             pcntl_signal(SIGTERM, function () {
                 //echo "Daemon process caught SIGTERM\n";
                 if ($this->childPids) {
                     foreach (array_keys($this->childPids) as $pid) {
                         //echo "Sending SIGKILL to child $pid\n";
                         posix_kill($pid, SIGKILL);
                     }
                 }
                 //echo "Daemon process $this->pid exiting\n";
                 unlink($this->pidFile);
                 exit;
             });
         } else {
             //echo "Successfully daemonized. PID $pid written to $this->pidFile\n";
             file_put_contents($this->pidFile, $pid);
             exit;
         }
     }
     $this->childPids = $pids = [];
     if ($this->fork) {
         RE_FORK:
         for ($c = count($this->childPids); $c < $this->fork; $c++) {
             $pid = pcntl_fork();
             if ($pid > 0) {
                 // "Forked child with PID $pid\n";
                 $this->childPids[$pid] = time();
             } else {
                 $this->pid = getmypid();
                 $this->isChild = true;
                 $this->isDaemon = false;
                 goto DO_WORK;
             }
         }
         while (count($this->childPids)) {
             $status = 0;
             $exitedPid = pcntl_wait($status);
             unset($this->childPids[$exitedPid]);
             if ($this->refork) {
                 goto RE_FORK;
             }
         }
         goto END_FORK;
     }
     DO_WORK:
     $func = $this->callback;
     $func();
     exit;
     END_FORK:
     exit;
 }
コード例 #19
0
function check_wait($pid)
{
    global $pids, $procs;
    array_push($pids, $pid);
    if (count($pids) > $procs) {
        $pid = pcntl_wait($status);
        array_remove($pid, $pids);
    }
}
コード例 #20
0
 public function execute()
 {
     $server = TTMServer::primary();
     if ($server instanceof FakeTTMServer) {
         $this->error("Translation memory is not configured properly", 1);
     }
     $dbw = $server->getDB(DB_MASTER);
     $this->statusLine('Deleting sources.. ', 1);
     $dbw->delete('translate_tms', '*', __METHOD__);
     $this->output('translations.. ', 1);
     $dbw->delete('translate_tmt', '*', __METHOD__);
     $this->output('fulltext.. ', 1);
     $dbw->delete('translate_tmf', '*', __METHOD__);
     $table = $dbw->tableName('translate_tmf');
     $dbw->query("DROP INDEX tmf_text ON {$table}");
     $this->output('done!', 1);
     $this->statusLine('Loading groups... ', 2);
     $groups = MessageGroups::singleton()->getGroups();
     $this->output('done!', 2);
     $threads = $this->getOption('threads', 1);
     $pids = array();
     foreach ($groups as $id => $group) {
         if ($group->isMeta()) {
             continue;
         }
         // Fork to avoid unbounded memory usage growth
         $pid = pcntl_fork();
         if ($pid === 0) {
             // Child, reseed because there is no bug in PHP:
             // http://bugs.php.net/bug.php?id=42465
             mt_srand(getmypid());
             $this->exportGroup($group, $threads > 1);
             exit;
         } elseif ($pid === -1) {
             // Fork failed do it serialized
             $this->exportGroup($group);
         } else {
             $this->statusLine("Forked thread {$pid} to handle {$id}\n");
             $pids[$pid] = true;
             // If we hit the thread limit, wait for any child to finish.
             if (count($pids) >= $threads) {
                 $status = 0;
                 $pid = pcntl_wait($status);
                 unset($pids[$pid]);
             }
         }
     }
     // Return control after all threads have finished.
     foreach (array_keys($pids) as $pid) {
         $status = 0;
         pcntl_waitpid($pid, $status);
     }
     $this->statusLine('Adding fulltext index...', 9);
     $table = $dbw->tableName('translate_tmf');
     $dbw->query("CREATE FULLTEXT INDEX tmf_text ON {$table} (tmf_text)");
     $this->output(' done!', 9);
 }
コード例 #21
0
 /**
  * @throws \Exception when child process ends with an Exception
  *
  * @return mixed
  */
 protected function handleParentProcess()
 {
     pcntl_wait($status);
     $result = $this->ipc->get();
     if ($result instanceof ExceptionDataHolder) {
         throw new IsolatedCallbackExecutionException($result);
     }
     return $result;
 }
コード例 #22
0
ファイル: ChildProcessTest.php プロジェクト: jinchunguang/qpm
 public function testProcessFork()
 {
     $child = Process::fork(function () {
         exit;
     });
     $this->assertTrue($child instanceof ChildProcess);
     $st = 0;
     $cpid = pcntl_wait($st);
     $this->assertEquals($cpid, $child->getPid());
 }
コード例 #23
0
ファイル: PoolWorker.php プロジェクト: rubn-g/multitask
 /**
  * @param Thread $thread
  */
 public function add($job, $delay = 0)
 {
     if (count($this->threads) >= $this->size) {
         unset($this->threads[pcntl_wait($status)]);
     }
     $this->delay($delay);
     $thread = new Thread($job);
     $thread->start();
     $this->threads[$thread->getPid()] = $thread;
 }
コード例 #24
0
ファイル: ProcessManager.php プロジェクト: phresque/spork
 public function waitForNext($hang = true)
 {
     if (-1 === ($pid = pcntl_wait($status, ($hang ? WNOHANG : 0) | WUNTRACED))) {
         throw new ProcessControlException('Error while waiting for next fork to exit');
     }
     if (isset($this->forks[$pid])) {
         $this->forks[$pid]->processWaitStatus($status);
         return $this->forks[$pid];
     }
 }
コード例 #25
0
 /**
  *
  */
 private function signalHandlersParent()
 {
     $root = $this;
     pcntl_signal(SIGCHLD, function () use($root) {
         while (($pid = pcntl_wait($status, WNOHANG)) > 0) {
             array_diff($root->children, [$pid]);
         }
     });
     pcntl_signal_dispatch();
 }
コード例 #26
0
ファイル: task_ctl.php プロジェクト: vincenttone/daf
 /**
  * @return $this
  */
 public function wait_children()
 {
     while ($this->_current_pids) {
         $pid = pcntl_wait($status);
         if ($pid > 0) {
             unset($this->_current_pids[$pid]);
             $this->_current_process_count--;
         }
     }
     return $this;
 }
コード例 #27
0
ファイル: Fork.php プロジェクト: dsmithhayes/extended
 /**
  * @param \Extended\Process\Runnable $child
  *      A runnable process to fork
  */
 public function fork(Runnable $child)
 {
     $this->pid = pcntl_fork();
     if ($this->pid == -1) {
         $error = pcntl_strerror(pcntl_get_last_error());
         throw new ProcessException('Unable to fork the process: ' . $error);
     } elseif ($this->pid) {
         return pcntl_wait($this->pid);
     }
     self::$buffer->append($child->run());
 }
コード例 #28
0
 public function reapChild()
 {
     // Check if any child process has terminated,
     // and if so remove it from memory
     $pid = pcntl_wait($status, WNOHANG);
     if ($pid < 0) {
         throw new \Exception("Out of memory");
     } elseif ($pid > 0) {
         unset($this->processes[$pid]);
     }
 }
コード例 #29
0
/**
 * master.
 * 
 * to start and mantaince child Processes.
 * 
 * @param integer $maxChildren
 */
function master($maxChildren)
{
    for ($i = 0; $i < $maxChildren; $i++) {
        startWorker();
    }
    // 维持子进程数量
    while (true) {
        $status = null;
        pcntl_wait($status);
        startWorker();
    }
}
コード例 #30
0
ファイル: Gearman.php プロジェクト: recipe/scalr
 public function mainLoop()
 {
     $this->loadJobs();
     $this->poolPid = posix_getpid();
     $this->initSignalHandler();
     while (true) {
         $this->logger->info("MainLoop");
         if (!$this->terminating) {
             foreach ($this->jobs as $job => $settings) {
                 $startWorker = false;
                 if (count($settings['pids']) < $this->processesPerJob) {
                     $startWorker = true;
                     $this->logger->error("No process for job: {$job}. Starting...");
                 } else {
                     foreach ($settings['pids'] as $pid) {
                         if (!posix_kill($pid, 0)) {
                             $startWorker = true;
                             $this->logger->error("Process for job: {$job}. Not running. Starting...");
                             break;
                         }
                     }
                 }
                 if ($startWorker) {
                     $this->forkChild($job);
                 }
             }
         }
         $pid = pcntl_wait($status, WNOHANG);
         if ($pid > 0) {
             $this->logger->info(sprintf("wait() from child %s. Status: %d", $pid, $status));
             foreach ($this->jobs as $job => $settings) {
                 foreach ($settings['pids'] as $k => $wpid) {
                     if ($wpid && $wpid == $pid) {
                         $this->logger->warn("{$job} client worker died");
                         unset($settings['pids'][$k]);
                         $this->jobs[$job] = $settings;
                         break;
                     }
                 }
             }
         }
         if ($this->terminating) {
             $pids = 0;
             foreach ($this->jobs as $settings) {
                 $pids += count($settings['pids']);
             }
             if ($pids == 0) {
                 exit;
             }
         }
         sleep(10);
     }
 }