protected function startWorker() { $this->_connectRedis(); $run_count = 0; $queue = Config::get('queue', $this->worker_name); while (!$this->stop_work) { pcntl_signal_dispatch(); $job_info = $this->_redis->lPop($queue); if (!empty($job_info)) { try { $this->_do($job_info); } catch (Exception $e) { $this->logger->err($e); } } if ($this->stop_work) { $this->logger->debug("process get exit signo, pid: {$this->pid}"); break; } if (time() - $this->start_time >= $this->max_run_time) { $this->logger->debug("process running over the max run time: {$this->max_run_time}"); break; } if (++$run_count >= $this->max_job_count) { $this->logger->debug("process running over the max run count: {$this->max_job_count}"); break; } usleep(50000); } $this->_closeRedis(); }
public function loop() { $this->in_loop = true; while ($this->in_loop) { $conn = false; $read = array($this->socket); $write = null; $except = null; declare (ticks=1) { // stream_socket_accept() doesn't block on some(?) of the ARM systems // so, wrapping it into stream_select() which works always // see https://bugs.php.net/bug.php?id=62816 if (1 === @stream_select($read, $write, $except, null)) { $conn = @stream_socket_accept($this->socket, 0); } } if (false !== $conn) { $remote_addr = stream_socket_get_name($conn, true); if (false === $remote_addr) { $remote_addr = null; } call_user_func($this->callback, $conn, $remote_addr); } pcntl_signal_dispatch(); } }
protected function dispatch($blocking) { $this->selectStreams($this->readStreams, $this->writeStreams, $blocking ? $this->getTimeout() : 0); if (!empty($this->timerExpires)) { $time = (int) (\microtime(true) * self::MILLISEC_PER_SEC); while (!$this->timerQueue->isEmpty()) { list($watcher, $expiration) = $this->timerQueue->top(); $id = $watcher->id; if (!isset($this->timerExpires[$id]) || $expiration !== $this->timerExpires[$id]) { $this->timerQueue->extract(); // Timer was removed from queue. continue; } if ($this->timerExpires[$id] > $time) { // Timer at top of queue has not expired. break; } $this->timerQueue->extract(); if ($watcher->type & Watcher::REPEAT) { $this->activate([$watcher]); } else { $this->cancel($id); } // Execute the timer. $callback = $watcher->callback; $callback($id, $watcher->data); } } if ($this->signalHandling) { \pcntl_signal_dispatch(); } }
/** * run the worker */ protected function startWorker() { $run_count = 0; while (!$this->stop_work) { pcntl_signal_dispatch(); try { $this->_do(); } catch (Exception $e) { $this->logger->err($e); } if ($this->stop_work) { $this->logger->debug("process get exit signo, pid: {$this->pid}"); break; } if (time() - $this->start_time >= $this->max_run_time) { $this->logger->debug("process running over the max run time: {$this->max_run_time}"); break; } if (++$run_count >= $this->max_job_count) { $this->logger->debug("process running over the max run count: {$this->max_job_count}"); break; } usleep(50000); } }
public function execute(array $matches, $rest, $url) { //Debug::setLogger(new STDOUTLogger()); $cfg = new Config(); $currencyMeta = $cfg->getCurrencyMeta(); $scanner = new BillScannerDriver(); $scanner->stop(); foreach ([SIGINT, SIGTERM] as $signal) { pcntl_signal($signal, function () use($scanner) { $scanner->stop(); }); } $oldState = []; $scanner->attachObserver('tick', function () { pcntl_signal_dispatch(); })->attachObserver('billInserted', function ($desc) use($currencyMeta, $scanner) { $denoms = $currencyMeta->getDenominations(); if ($desc['billIndex'] === 4) { $scanner->setBillRejected(true); echo "-=[ REJECTING BILL FROM CLI-DRIVER ]=-\n"; } echo 'Bill Inserted(' . $desc['billIndex'] . '): ', $currencyMeta->format($denoms[$desc['billIndex']]), ' (', $currencyMeta->getISOCode(), ")\n"; })->attachObserver('stateChanged', function ($desc) use(&$oldState) { foreach ($desc as $state => $value) { if (isset($oldState[$state]) && $oldState[$state] !== $value) { echo $state, ": ", $value ? 'true' : 'false', "\n"; } $oldState[$state] = $value; } })->attachObserver('driverStopped', function () { echo "Driver stopped\n"; })->run(); }
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."); }
public function run() { if (!$this->_connect()) { Logger::warning('Failed to connect.'); return false; } Logger::debug('Connected :-)'); if ($pcntl = extension_loaded('pcntl')) { Logger::debug('Trapping signals...'); $this->_trapSignals(); } Logger::debug('Entering loop.'); $start = time(); while (is_resource($this->socket->resource())) { if ($pcntl) { pcntl_signal_dispatch(); } if ($start < time() - 60 * 30) { foreach ($this->_plugins['poll'] as $class) { $this->_respond($this->_channels, $class->poll()); } $start = time(); } $r = [$this->socket->resource()]; $w = []; $e = []; if (stream_select($r, $w, $e, 2) !== 1) { continue; } $this->_process($this->_read()); } $this->_disconnect(); }
/** * Start * * @param OutputInterface $output * * @return void */ protected function start(OutputInterface $output) { $output->writeln('Starting daemon...'); if (file_exists($this->pidfile)) { $output->writeln('<error>Daemon process is already running</error>'); return null; } $pid = pcntl_fork(); if ($pid == -1) { $output->writeln('<error>Could not fork</error>'); return null; } elseif ($pid) { file_put_contents($this->pidfile, $pid); $output->writeln('Daemon started with PID ' . $pid); } else { $terminated = false; pcntl_signal(SIGTERM, function ($signo) use(&$terminated) { if ($signo == SIGTERM) { $terminated = true; } }); while (!$terminated) { $this->executeOperation(); pcntl_signal_dispatch(); sleep(1); } $output->writeln('Daemon stopped'); } }
/** * @param EventInterface $event */ public function checkSignals(EventInterface $event) { pcntl_signal_dispatch(); if ($this->shouldStop) { $event->stopPropagation(); } }
public function listen() { $attempts = 0; $this->supervisor->workerReporter->reportJob('LISTENING'); while (true) { if ($this->supervisor->canIOffDuty()) { break; } $this->report('PING'); if ($this->job = $this->supervisor->newJob()) { Log::info("Worker [{$this->supervisor->pid}], recv job [ {$this->getJobId()} ]"); $attempts = 0; try { // 不允许输出, 当Command是通过http请求创建时,进程输出内容会使进程意外结束 ob_start(); $this->start($this->job); ob_get_clean(); Log::info("Worker [{$this->supervisor->pid}], job done [ {$this->getJobId()} ]"); } catch (\Exception $e) { Log::info("Worker [{$this->supervisor->pid}], job err [ {$this->getJobId()} ]"); Log::error($e); $this->supervisor->workerReporter->reportJob('LISTENING'); } $this->supervisor->removeJobFromReserved($this->job); } else { if ($attempts !== 0) { sleep(3); } $attempts++; } pcntl_signal_dispatch(); } Log::info("Worker [{$this->supervisor->pid}], off duty"); $this->supervisor->offDuty(); }
/** * Setting up and installing the data handler. * @param array $entries */ public function __construct($entries) { $this->entries = $entries; pcntl_signal_dispatch(); pcntl_signal(SIGTERM, array($this, 'signalHandler')); pcntl_signal(SIGCHLD, array($this, 'signalHandler')); }
protected function execute(InputInterface $input, OutputInterface $output) { $this->registerSignalHandlers($output); $repeat = !$input->getOption('once'); $sleep = (int) $input->getOption('sleep'); if (empty($sleep)) { $sleep = 2; } $verbose = (bool) $input->getOption('verbose'); $cacheManager = $this->getCacheManager(); if ($cacheManager instanceof LoggerAwareInterface && $verbose) { $cacheManager->setLogger(new ConsoleLogger($output, [LogLevel::INFO => OutputInterface::VERBOSITY_NORMAL, LogLevel::DEBUG => OutputInterface::VERBOSITY_NORMAL])); } do { $cacheManager->warmUpCacheIfNeeded(); pcntl_signal_dispatch(); if ($repeat) { if ($verbose) { $output->writeln("Sleeping for {$sleep} seconds..."); } sleep($sleep); pcntl_signal_dispatch(); } } while ($repeat); }
public function run() { $running = array(); // Handle SIGTERM calls pcntl_signal(SIGTERM, array($this, 'terminate')); pcntl_signal(SIGINT, array($this, 'terminate')); while (true) { // Check for any signals we've received pcntl_signal_dispatch(); // Check the running workers $this->check_workers(); // Do we have workers to spare? if (count($this->workers) === $this->options['max_workers']) { // At maximum workers, wait a cycle printf('[ ] Out of workers' . PHP_EOL); sleep(LOOP_INTERVAL); continue; } // Find any new jobs, or wait for one $job = $this->get_next_job(); if (empty($job)) { // No job to run, try again in a second sleep(LOOP_INTERVAL); continue; } // Spawn worker try { $this->run_job($job); } catch (Exception $e) { break; } // Go again! } $this->terminate(); }
/** * 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'; }
/** * Consumes messages off of the queue * * @codeCoverageIgnore * * @param string $queue */ public function consume($queue) { $this->bindSignals(); while ($this->tick($queue)) { pcntl_signal_dispatch(); } }
/** * Test signal interrupt when a stream is attached to the loop * @dataProvider signalProvider */ public function testSignalInterruptWithStream($sigName, $signal) { if (!extension_loaded('pcntl')) { $this->markTestSkipped('"pcntl" extension is required to run this test.'); } // dispatch signal handler every 10ms $this->loop->addPeriodicTimer(0.01, function () { pcntl_signal_dispatch(); }); // add stream to the loop list($writeStream, $readStream) = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP); $this->loop->addReadStream($readStream, function ($stream, $loop) { /** @var $loop LoopInterface */ $read = fgets($stream); if ($read === "end loop\n") { $loop->stop(); } }); $this->loop->addTimer(0.05, function () use($writeStream) { fwrite($writeStream, "end loop\n"); }); $this->setUpSignalHandler($signal); // spawn external process to send signal to current process id $this->forkSendSignal($signal); $this->loop->run(); $this->assertTrue($this->_signalHandled); }
/** * Use cases: * in_array(SIGHUP, $helper->takeSignals()) * or * array_intersect([SIGINT, SIGTERM], $helper->takeSignals()) * * @return array List with signals (integer codes), can contains duplicates. Newest signal will be first. */ public function takeSignals() { // All signals will caught only inside this call. pcntl_signal_dispatch(); $signals = $this->signals; $this->signals = []; return $signals; }
public function askedToStop() { // This needs to be called to dispatch the signals received by the current // process. The PHP process doesn't do that by default, if you have some piece // of code that it's executed periodically then this is the best method pcntl_signal_dispatch(); return !is_null($this->signal); }
/** * {@inheritdoc} */ public function isAwaitingStopped() { if (static::$hasPcntl) { // TODO: could be handled with QueueEvent::EVENT_IDLE pcntl_signal_dispatch(); } return parent::isAwaitingStopped(); }
public function init(LoopInterface $loop = null) { $this->loop = is_null($loop) ? \React\EventLoop\Factory::create() : $loop; $this->loop->addPeriodicTimer(0.1, array($this, 'checkSchedule')); $this->bindSignals(); $this->loop->addPeriodicTimer(1, function () { pcntl_signal_dispatch(); }); }
public function init() { pcntl_signal(SIGTERM, [$this, 'signalHandler']); pcntl_signal_dispatch(); parent::init(); if (self::$queue === null) { self::$queue = Yii::$app->{$this->queueObjectName}; } }
public function termOne($pid, $signal = SIGTERM) { $plug = \PMVC\plug(PLUGIN); if (isset($plug[CHILDREN][$pid])) { $plug->log('Stopping child ' . $pid); $result = posix_kill($pid, $signal); pcntl_signal_dispatch(); } }
/** * @return bool True if the loop should continue, false otherwise */ public function shouldContinue() { if (!$this->isHandlerInstalled) { pcntl_signal(SIGTERM, [$this, 'handler']); pcntl_signal(SIGINT, [$this, 'handler']); $this->isHandlerInstalled = true; } pcntl_signal_dispatch(); return $this->isRunning; }
public function testSignal() { $this->assertFalse(self::$terminated); usleep(100); posix_kill(posix_getpid(), SignalHandler::SIGINT); usleep(100); pcntl_signal_dispatch(); usleep(100); $this->assertTrue(self::$terminated); }
public function process() { $i = 0; while ($this->isRunning && $i < 100) { pcntl_signal_dispatch(); echo $this->pid . "\t" . $i . PHP_EOL; sleep(rand(1, 3)); $i++; } }
/** * Execute `pcntl_signal_dispatch` and process all registered handlers. * * @return $this */ public function dispatch() { pcntl_signal_dispatch(); foreach ($this->signalQueue as $signal) { foreach ($this->handlers[$signal] as &$callable) { call_user_func($callable, $signal); } } return $this; }
public function listen() { pcntl_signal(SIGTERM, array($this, 'delete')); pcntl_signal(SIGINT, array($this, 'delete')); echo 'Listening for process termination'; echo PHP_EOL; do { pcntl_signal_dispatch(); sleep(5); } while ($this->processActive); }
public function onEventAccept($socket, $event) { $conn = $this->acceptSocket(); $remote_addr = stream_socket_get_name($conn, true); if (false === $remote_addr) { $remote_addr = null; } self::log('Socket', 'callback'); call_user_func($this->callback, $conn, $remote_addr); pcntl_signal_dispatch(); }
public function start() { $this->bindSignals(); //master process shutdown request handler $this->loop->addPeriodicTimer(1, function () { pcntl_signal_dispatch(); }); foreach ($this->daemons as $daemon) { $this->daemons[$daemon] = $this->newInstance($daemon); } }
function do_task() { echo "创建子进程成功,进程号:" . posix_getpid() . ",等待主进程发送信号...\n"; while (1) { sleep(1); pcntl_signal_dispatch(); sleep(2); echo "结束子进程" . posix_getpid() . "...\n"; exit; } }