Beispiel #1
0
 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();
     }
 }
Beispiel #3
0
 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();
     }
 }
Beispiel #4
0
 /**
  * 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);
     }
 }
Beispiel #5
0
 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();
 }
Beispiel #6
0
 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.");
 }
Beispiel #7
0
 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();
 }
Beispiel #8
0
 /**
  * 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');
     }
 }
Beispiel #9
0
 /**
  * @param EventInterface $event
  */
 public function checkSignals(EventInterface $event)
 {
     pcntl_signal_dispatch();
     if ($this->shouldStop) {
         $event->stopPropagation();
     }
 }
Beispiel #10
0
 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();
 }
Beispiel #11
0
 /**
  * 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);
 }
Beispiel #13
0
 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();
 }
Beispiel #14
0
 /**
  * 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';
 }
Beispiel #15
0
 /**
  * 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;
 }
Beispiel #18
0
 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();
 }
Beispiel #20
0
 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();
     });
 }
Beispiel #21
0
 public function init()
 {
     pcntl_signal(SIGTERM, [$this, 'signalHandler']);
     pcntl_signal_dispatch();
     parent::init();
     if (self::$queue === null) {
         self::$queue = Yii::$app->{$this->queueObjectName};
     }
 }
Beispiel #22
0
 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);
 }
Beispiel #25
0
 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++;
     }
 }
Beispiel #26
0
 /**
  * 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();
 }
Beispiel #29
0
 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);
     }
 }
Beispiel #30
0
Datei: fork.php Projekt: xqy/php
function do_task()
{
    echo "创建子进程成功,进程号:" . posix_getpid() . ",等待主进程发送信号...\n";
    while (1) {
        sleep(1);
        pcntl_signal_dispatch();
        sleep(2);
        echo "结束子进程" . posix_getpid() . "...\n";
        exit;
    }
}