/** * 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'; }
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."); }
/** * Handler for process signals. * * @param int $signo * @param int $pid * @param int $status */ public function childSignalHandler($signo = null, $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) { $this->logger->debug('TestCase was successful finished.', ['pid' => $pid]); } else { $this->logger->info('Process exited with status != 0.', ['pid' => $pid, 'exitCode' => $exitCode]); $this->exitCode = $exitCode; } 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 $this->logger->debug('Adding process to signal queue.', ['pid' => $pid]); $this->signalQueue[$pid] = $status; } } $pid = pcntl_waitpid(-1, $status, WNOHANG); } }
public function child_signal_handler($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->current_jobs[$pid])) { $exit_code = pcntl_wexitstatus($status); if ($exit_code != 0) { echo "{$pid} exited with status " . $exit_code . "\n"; } unset($this->current_jobs[$pid]); } else { if ($pid) { //Oh no, our job has finished before this parent process could even note that it had been launched! echo "..... Adding {$pid} to the signal queue ..... \n"; $this->signal_queue[$pid] = $status; } } $pid = pcntl_waitpid(-1, $status, WNOHANG); } return true; }
public function getStatus($status) { if (pcntl_wifexited($status)) { return pcntl_wexitstatus($status); } return 1; }
/** * run a callback in parrallel thread * * @param callable $callback * @return void */ public function run(\Closure $callback = null) { $callback = $callback ?: function () { }; $children = array(); while (!empty($this->works)) { $items = array_pop($this->works); $pid = pcntl_fork(); if (-1 == $pid) { throw new \RuntimeException('無法使用子程序!'); } elseif ($pid) { //子程序start $children[] = $pid; $this->onStart($pid); } else { try { //子程序處理 callback $callback($items); exit(0); } catch (\Exception $e) { exit($e->getCode()); } } } if ($children) { foreach ($children as $child) { $res = pcntl_waitpid($child, $status); if ($res == -1 || $res > 0) { //子程序end $status = pcntl_wexitstatus($status); $this->onExit($child, $status); } } } }
protected function waitForBackground(InputInterface $input, OutputInterface $output) { $lastMemory = memory_get_usage(true); while (true) { $memory = memory_get_usage(true); if ($memory != $lastMemory) { $output->writeln(sprintf("memory change: %d, from %d to %d", $memory - $lastMemory, $lastMemory, $memory)); } $lastMemory = $memory; $status = 0; $pid = pcntl_waitpid(-1, $status, WNOHANG); if ($pid == 0) { // no child process has quit //usleep(200 * 1000); } else { if ($pid > 0) { // child process with pid = $pid exits $exitStatus = pcntl_wexitstatus($status); $this->onChildProcessExit($pid, $exitStatus, $input, $output); } else { // error $errno = pcntl_get_last_error(); if ($errno == PCNTL_ECHILD) { // all children finished mdebug("No more BackgroundProcessRunner children, continue ..."); break; } else { // some other error throw new \RuntimeException("Error waiting for process, error = " . pcntl_strerror($errno)); } } } } return $this->isFailed ? self::EXIT_CODE_COMMON_ERROR : self::EXIT_CODE_OK; }
function excute($url = '', $data) { connectRedis(); $response = array(); $loop = count($data); for ($i = 0; $i < $loop; $i++) { # code... $pid = pcntl_fork(); if (!$pid) { // sleep(1); print "In child {$i}\n"; if (array_key_exists($i, $data)) { $x = 7; $k = get_url($data[$i]); setRedis("data", $i); } exit($i); } } #process while (pcntl_waitpid(0, $status) != -1) { $status = pcntl_wexitstatus($status); echo "Child {$status} completed\n"; } // dd($response); return $response; }
protected function onChildExit($pid, $status) { $workerId = -1; foreach ($this->workers as $k => $worker) { if ($pid == $worker->getPid()) { $workerId = $k; break; } } if ($workerId == -1) { throw new RuntimeException('unknown child pid'); } if ($this->gotTerm) { $this->workers[$workerId]->callFromMasterOnTerm($status); unset($this->workers[$workerId]); return; } if (pcntl_wifexited($status) && 0 == pcntl_wexitstatus($status)) { $this->workers[$workerId]->callFromMasterOnSuccess($status); unset($this->workers[$workerId]); return; } $this->workers[$workerId]->callFromMasterOnError($status); $this->internalSpawnWorker($this->workers[$workerId]); }
/** * 执行同步 * @return bool */ public function run() { while (1) { $online_user = $this->get_data('Online')->get_online_list(); $user_num = count($online_user); if (empty($online_user)) { sleep($this->_set_interval_time); #等待一下 break; } $threads = array(); foreach ($this->_sync_tables as $table) { $pid = pcntl_fork(); if ($pid == -1) { echo "FORK ERROR \n"; return false; } else { if ($pid) { $threads[] = $pid; echo "CREATE THREAD SUCESS CUR THREAD ID IS {$pid}\n"; } else { $exec_starttime = microtime(true); $this->sync($online_user, $table); echo "syncdb {$user_num} execute {$table['table_name']} func run " . (microtime(true) - $exec_starttime) . "\n"; exit(1); } } } /* foreach($this->_sync_union as $union_table){ $pid = pcntl_fork(); if($pid == -1){ echo "FORK ERROR \n"; return false; }else{ if($pid){ $threads[] = $pid; echo "CREATE THREAD SUCESS CUR THREAD ID IS {$pid}\n"; }else{ $exec_starttime = microtime(true); $this->sync_union($online_user,$union_table); echo "syncdb {$user_num} execute {$union_table['table_name']} func run ".(microtime(true)-$exec_starttime)."\n"; exit(1); } } }*/ foreach ($threads as $thread_id) { pcntl_waitpid($thread_id, $status); echo "THREAD {$thread_id} NOW EXIT\n"; if (pcntl_wifexited($status)) { $c = pcntl_wexitstatus($status); echo "CHILD EXIT PID {$thread_id} STATUS {$c}\n"; } } echo "SyncDb SUCESS\n"; sleep($this->_set_interval_time); #等待一下 } }
private function exitStatusOfLastChild($status) { $exitStatusOfLastChild = pcntl_wexitstatus($status); $lastChildExitedNormally = pcntl_wifexited($status); if ($exitStatusOfLastChild === 0 && !$lastChildExitedNormally) { $exitStatusOfLastChild = 1; } return $exitStatusOfLastChild; }
/** * @return bool */ public function isCompleted() { $pid = pcntl_waitpid($this->getPid(), $status, WNOHANG); if ($pid == -1 || $pid === $this->getPid()) { $this->status = pcntl_wexitstatus($status); return true; } return false; }
/** * Wait for the background process to exit */ public function join() { if ($this->_started) { $status = null; pcntl_waitpid($this->_childPid, $status); $this->_started = false; $this->_returnCode = pcntl_wexitstatus($status); } return $this->_returnCode; }
/** * Start a thread */ public function start() { $this->fork(); if (!$this->pid) { $this->run(); if (substr(PHP_SAPI, 0, 3) == 'cli') { exit; } pcntl_wexitstatus(null); } }
function pleac_Running_Another_Program() { // Run a simple command and retrieve its result code. exec("vi {$myfile}", $output, $result_code); // ----------------------------- // Use the shell to perform redirection. exec('cmd1 args | cmd2 | cmd3 >outfile'); exec('cmd args <infile >outfile 2>errfile'); // ----------------------------- // Run a command, handling its result code or signal. $pid = pcntl_fork(); if ($pid == -1) { die('cannot fork'); } elseif ($pid) { pcntl_waitpid($pid, $status); if (pcntl_wifexited($status)) { $status = pcntl_wexitstatus($status); echo "program exited with status {$status}\n"; } elseif (pcntl_wifsignaled($status)) { $signal = pcntl_wtermsig($status); echo "program killed by signal {$signal}\n"; } elseif (pcntl_wifstopped($status)) { $signal = pcntl_wstopsig($status); echo "program stopped by signal {$signal}\n"; } } else { pcntl_exec($program, $args); } // ----------------------------- // Run a command while blocking interrupt signals. $pid = pcntl_fork(); if ($pid == -1) { die('cannot fork'); } elseif ($pid) { // parent catches INT and berates user declare (ticks=1); function handle_sigint($signal) { echo "Tsk tsk, no process interruptus\n"; } pcntl_signal(SIGINT, 'handle_sigint'); while (!pcntl_waitpid($pid, $status, WNOHANG)) { } } else { // child ignores INT and does its thing pcntl_signal(SIGINT, SIG_IGN); pcntl_exec('/bin/sleep', array('10')); } // ----------------------------- // Since there is no direct access to execv() and friends, and // pcntl_exec() won't let us supply an alternate program name // in the argument list, there is no way to run a command with // a different name in the process table. }
/** * Analyzes the passed status code of a process and sets properties accordingly. * * @param int $status * @author Dan Homorodean <*****@*****.**> */ public function __construct($status) { if (pcntl_wifexited($status)) { $this->status = self::STATUS_EXITED; $this->exitCode = pcntl_wexitstatus($status); } elseif (pcntl_wifsignaled($status)) { $this->status = self::STATUS_SIGNALED; $this->reasonSignal = pcntl_wtermsig($status); } elseif (pcntl_wifstopped($status)) { $this->status = self::STATUS_STOPPED; $this->reasonSignal = pcntl_wstopsig($status); } }
function sig_handler($signo) { switch ($signo) { case SIGCHLD: while (($x = pcntl_waitpid(0, $status, WNOHANG)) != -1) { if ($x == 0) { break; } $status = pcntl_wexitstatus($status); } break; } }
function test_exit_waits() { print "\n\nTesting pcntl_wifexited and wexitstatus...."; $pid = pcntl_fork(); if ($pid == 0) { sleep(1); exit(-1); } else { $options = 0; pcntl_waitpid($pid, $status, $options); if (pcntl_wifexited($status)) { print "\nExited With: " . pcntl_wexitstatus($status); } } }
protected function waitForBackgroundProcesses() { //$lastMemory = memory_get_usage(true); while (true) { //$memory = memory_get_usage(true); //if ($memory != $lastMemory) { // echo( // sprintf("memory change: %d, from %d to %d", $memory - $lastMemory, $lastMemory, $memory) // . PHP_EOL // ); //} //$lastMemory = $memory; pcntl_signal_dispatch(); $status = 0; $pid = pcntl_waitpid(-1, $status, WNOHANG); if ($pid == 0) { // no child process has quit usleep(200 * 1000); } else { if ($pid > 0) { // child process with pid = $pid exits $exitStatus = pcntl_wexitstatus($status); $runner = $this->runningProcesses[$pid]; if (!$runner instanceof CommandRunner) { throw new \LogicException("Cannot find command runner for process pid = %d", $pid); } unset($this->runningProcesses[$pid]); $runner->onProcessExit($exitStatus, $pid); $newPid = $runner->run(); if ($newPid > 0) { $this->runningProcesses[$newPid] = $runner; } } else { // error $errno = pcntl_get_last_error(); if ($errno == PCNTL_ECHILD) { // all children finished mdebug("No more BackgroundProcessRunner children, continue ..."); break; } else { // some other error throw new \RuntimeException("Error waiting for process, error = " . pcntl_strerror($errno)); } } } } }
public function execute(CommittedJob $job, LogProvider $logProvider) { $traceStream = tmpfile(); $child = pcntl_fork(); if (!$child) { $this->executeInChild($job, $logProvider, $traceStream); } $childStatus = null; pcntl_wait($childStatus); $exitCode = pcntl_wexitstatus($childStatus); if ($exitCode !== 0) { rewind($traceStream); $e = new \RuntimeException(sprintf("Process for job %s exited non-zero: %d", $job->getId(), $exitCode)); $e->traceString = stream_get_contents($traceStream); throw $e; } }
public function childSignalHandler($signo, $pid = null, $status = null) { if (!$pid) { $pid = pcntl_waitpid(-1, $status, WNOHANG); } while ($pid > 0) { if ($pid && isset($this->currentJobs[$pid])) { $exitCode = pcntl_wexitstatus($status); if ($exitCode != 0) { } unset($this->currentJobs[$pid]); } else { if ($pid) { $this->signalQueue[$pid] = $status; } } $pid = pcntl_waitpid(-1, $status, WNOHANG); } return true; }
function executeAllChecks() { $fedsList = $this->getDataFromJson->obtainFederationsList(); $this->storeResultsDb->storeFedsIntoDb($fedsList); $this->storeResultsDb->cleanOldEntityChecks(); $idpList = $this->getDataFromJson->obtainIdPList(); $this->storeResultsDb->updateIgnoredEntities(); $count = 0; for ($i = 0; $i < $this->parallel; $i++) { $pid = pcntl_fork(); if (!$pid) { sleep(1); //In child $this->storeResultsDb->resetDbConnection(); print "Executing check for " . $idpList[$count]['entityID'] . "\n"; $this->executeIdPchecks($idpList[$count], $this->fedsDisabled); return false; } $count++; } while (pcntl_waitpid(0, $status) != -1) { $status = pcntl_wexitstatus($status); if ($count < count($idpList)) { $pid = pcntl_fork(); if (!$pid) { sleep(1); //In child $this->storeResultsDb->resetDbConnection(); print "Executing check for " . $idpList[$count]['entityID'] . "\n"; $this->executeIdPchecks($idpList[$count], $this->fedsDisabled); return false; } $count++; } } // End of all cycles $this->storeResultsDb->resetDbConnection(); $this->storeResultsDb->deleteOldEntities(); $this->storeResultsDb->storeFederationStats(); return true; }
/** * Seperate the job from the worker via pcntl_fork * * @param Job $job */ public function perform(Job $job) { $this->child = Resque::fork(); // Forked and we're the child. Run the job. if ($this->child === 0) { parent::perform($job); exit(0); } // Parent process, sit and wait if ($this->child > 0) { $status = 'Forked ' . $this->child . ' at ' . strftime('%F %T'); $this->worker->updateProcLine($status); $this->worker->log($status); // Wait until the child process finishes before continuing pcntl_wait($status); $exitStatus = pcntl_wexitstatus($status); if ($exitStatus !== 0) { $job->fail(new Job\DirtyExitException('Job exited with exit code ' . $exitStatus)); } } $this->child = null; }
/** * Start serving requests to the application * @param Kelpie_Application */ public function start($app) { if (!($socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) { throw new Kelpie_Exception(socket_strerror(socket_last_error())); } if (!socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1)) { throw new Kelpie_Exception(socket_strerror(socket_last_error())); } if (!socket_bind($socket, $this->_host, $this->_port)) { throw new Kelpie_Exception(socket_strerror(socket_last_error())); } if (!socket_listen($socket)) { throw new Kelpie_Exception(socket_strerror(socket_last_error())); } // Prefork a number of child processes to handle incoming connections $maxConcurrency = 5; $procs = array(); while (true) { if (-1 == ($pid = pcntl_fork())) { throw new Kelpie_Exception('Could not fork'); } else { if ($pid == 0) { $this->_child($socket, $app); exit(0); } else { $procs[$pid] = $pid; } } if (count($procs) >= $maxConcurrency) { if (-1 == ($pid = pcntl_wait($status))) { throw new Kelpie_Exception('Something went wrong in pcntl_wait'); } $exitStatus = pcntl_wexitstatus($status); unset($procs[$pid]); } } }
public function actionIndex() { if ($rssSources = RssSources::findAll(["active" => "1"])) { foreach ($rssSources as $source) { Yii::$app->getDb()->close(); $pid = pcntl_fork(); Yii::$app->getDb()->open(); if (!$pid) { if ($source->is_full == 0) { $detector = new RssNewsDetectorComponent($source); $detector->run(); } else { $parser = new RssNewsParserComponent($source); $parser->run(); } Yii::$app->end(); } } while (pcntl_waitpid(0, $status) != -1) { $status = pcntl_wexitstatus($status); echo "Child {$status} completed\n"; } } }
if ($optGenerateContent === true) { $object->body = file_get_contents('xmltextsource.txt'); } $object->publish(); eZExecution::cleanExit(); } } } if ($script->verboseOutputLevel() > 0) { $cli->output("Main process: waiting for children..."); } $errors = 0; while (!empty($currentJobs)) { foreach ($currentJobs as $index => $pid) { if (pcntl_waitpid($pid, $exitStatus, WNOHANG) > 0) { $exitCode = pcntl_wexitstatus($exitStatus); if ($exitCode != 0) { $errors++; if (!$optQuiet) { if ($script->verboseOutputLevel() > 0) { $cli->output("process #{$pid} exited with code {$exitCode}"); } } } else { if (!$optQuiet) { if ($script->verboseOutputLevel() > 0) { $cli->output("process #{$pid} exited successfully"); } } } unset($currentJobs[$index]);
<?php $pid = pcntl_fork(); if ($pid == 1) { die("failed"); } else { if ($pid) { $status = 0; pcntl_wait($status, WUNTRACED); var_dump(pcntl_wifexited($status)); posix_kill($pid, SIGCONT); pcntl_wait($status); var_dump(pcntl_wifsignaled($status)); var_dump(pcntl_wifstopped($status)); var_dump(pcntl_wexitstatus($status)); var_dump(pcntl_wait($status, WNOHANG | WUNTRACED)); var_dump(pcntl_wait()); var_dump(pcntl_waitpid()); var_dump(pcntl_wifexited()); var_dump(pcntl_wifstopped()); var_dump(pcntl_wifsignaled()); var_dump(pcntl_wexitstatus()); var_dump(pcntl_wtermsig()); var_dump(pcntl_wstopsig()); } else { posix_kill(posix_getpid(), SIGSTOP); exit(42); } }
/** * Method to return the exit code of a terminated child process. * * @param integer $status The status parameter is the status parameter supplied to a successful call to pcntl_waitpid(). * * @return integer The child process exit code. * * @codeCoverageIgnore * @see pcntl_wexitstatus() * @since 11.3 */ protected function pcntlChildExitStatus($status) { return pcntl_wexitstatus($status); }
/** * Create a savegame fork. * * The savegame contains the current execution state, and can be resumed in * the event that the worker dies unexpectedly (for example, by encountering * a PHP fatal error). */ private function createSavegame() { // the current process will become the savegame $this->savegame = posix_getpid(); $pid = pcntl_fork(); if ($pid < 0) { throw new \RuntimeException('Unable to create savegame fork.'); } elseif ($pid > 0) { // we're the savegame now... let's wait and see what happens pcntl_waitpid($pid, $status); // worker exited cleanly, let's bail if (!pcntl_wexitstatus($status)) { posix_kill(posix_getpid(), SIGKILL); } // worker didn't exit cleanly, we'll need to have another go $this->createSavegame(); } }
/** * Spawns workers until one of them returns Sera_WorkerFarm::SPAWN_TERMINATE. * @return void */ public function spawn() { // needed for PHP 5.2 if (!function_exists('pcntl_signal_dispatch')) { declare (ticks=1); } $this->catchSignals(); $this->_children = array(); $parent = getmypid(); $this->onStart(); $this->_logger->info("spawning workers"); // enter spawn loop while (!$this->_terminate || count($this->_children)) { // needed for PHP 5.3 if (function_exists('pcntl_signal_dispatch')) { pcntl_signal_dispatch(); } // if we haven't hit the process limit yet if (!$this->_terminate && count($this->_children) < $this->getProcessLimit()) { $this->_spawnWorker($this->_children); } else { // patiently wait for a child to die if (($pid = pcntl_wait($status, WUNTRACED)) > 0) { unset($this->_children[$pid]); // check the exit code if (pcntl_wexitstatus($status) == self::SPAWN_TERMINATE && !$this->_terminate) { foreach (array_keys($this->_children) as $pid) { posix_kill($pid, SIGINT); } $this->_terminate = true; } } else { // if wait fails, check each child $this->_reapWorkers($this->_children); } } } $this->_logger->debug("workers are finished, terminating"); $this->onTerminate(0); }