/** * * @return Process */ public static function current() { $pid = \posix_getpid(); if (!self::$_current || !self::$_current->isCurrent()) { self::$_current = new Process($pid, \posix_getppid()); } return self::$_current; }
/** * @throws Comos\Qpm\Supervision\StopSignal */ protected function _startOne() { Logger::debug(__METHOD__ . '()'); $target = null; try { $target = \call_user_func($this->_config->getFactoryMethod()); } catch (StopSignal $ex) { Logger::debug('received stop signal'); throw $ex; } catch (\Exception $ex) { Logger::err($ex); \usleep(self::SLEEP_TIME_AFTER_ERROR); } if (!$target) { Logger::debug('fetched target is null. skipped'); return; } try { $process = Process::fork($target); $this->_children[$process->getPid()] = new ProcessStub($process, $this->_config); } catch (\Exception $ex) { Logger::err('exception', array('exception' => $ex)); \usleep(self::SLEEP_TIME_AFTER_ERROR); } }
public function testStart_Start2ProcessWithOnePidFile() { $pidfile = $this->_pidFile; $process = \Comos\Qpm\Process\Process::fork(function () use($pidfile) { $man = new Manager($pidfile); $man->start(); usleep(200 * 1000); }); usleep(100 * 1000); $man1 = new Manager($pidfile); $process1 = $man1->getProcess(); $this->assertTrue($process1 instanceof \Comos\Qpm\Process\Process); try { $man2 = new Manager($this->_pidFile); $man2->start(); $this->fail('expects Exception'); } catch (\Exception $e) { $st = 0; $pidfile = pcntl_wait($st); $this->assertEquals($pidfile, $process->getPid()); $this->assertEquals($pidfile, $process1->getPid()); $this->assertTrue(\pcntl_wifexited($st)); $this->assertTrue($e instanceof \Comos\Qpm\Pid\Exception); $this->assertEquals('process exists, no need to start a new one', $e->getMessage()); } }
public function testAllMethods() { parent::setUp(); $foo = function () { \usleep(150 * 1000); }; $child = Process\Process::fork($foo); $alive = $child->isAlive(); $this->assertTrue($alive); $this->assertNull($child->getStatus()->getTerminationSignal()); $this->assertNull($child->getStatus()->getExitCode()); $this->assertNull($child->getStatus()->getStopSignal()); $this->assertEquals(0, $child->getStatus()->getCode()); $this->assertFalse($child->getStatus()->isNormalExit()); $this->assertFalse($child->getStatus()->isSignaled()); $this->assertFalse($child->getStatus()->isStopped()); usleep(390 * 1000); $this->assertFalse($child->isAlive()); $this->assertFalse($child->getStatus()->isStopped()); $this->assertTrue($child->getStatus()->isNormalExit()); $this->assertEquals(0, $child->getStatus()->getTerminationSignal()); $this->assertEquals(0, $child->getStatus()->getStopSignal()); $this->assertFalse($child->getStatus()->isSignaled()); $this->assertEquals(0, $child->getStatus()->getExitCode()); }
public function testGetStatus() { $child = Process::fork(function () { usleep(100 * 1000); exit; }); $status = $child->getStatus(); $this->assertTrue($status instanceof \Comos\Qpm\Process\Status\ForkedChildStatus); $this->assertTrue($status instanceof \Comos\Qpm\Process\Status\NotExitStatus); $this->assertNull($status->getExitCode()); }
/** * * @return Process * @throws Exception */ public function getProcess() { $pidInfo = $this->_getPidInfoFromFile(); if (!$pidInfo) { throw new Exception('process does not exist'); } if ($this->_processExists($pidInfo[0], $pidInfo[1])) { return Process::process($pidInfo[0]); } throw new Exception('process does not exist'); }
public function stop() { if (!$this->_currentProcess->isCurrent()) { return; } $this->_stoped = true; foreach ($this->_children as $stub) { try { $stub->getProcess()->kill(); } catch (\Exception $ex) { Logger::err('fail to kill process', array('exception' => $ex)); } } while (count($this->_children)) { $status = 0; $pid = \pcntl_wait($status); unset($this->_children[$pid]); } }
<?php namespace Comos\Qpm\Supervision; require \dirname(__DIR__) . '/bootstrap.inc.php'; use Comos\Qpm\Process\Process; $file = $argv[1]; $file1 = $argv[2]; $configs = array(array('worker' => function () use($file) { \file_put_contents($file, 1, \FILE_APPEND); \usleep(1000 * 1000); }), array('worker' => function () use($file1) { \file_put_contents($file1, '2', \FILE_APPEND); \usleep(1000 * 500); }, 'quantity' => 2)); $supProcessCallback = function () use($configs) { $supervisor = Supervisor::multiGroupOneForOne($configs); $supervisor->start(); $supervisor->registerSignalHandler(); }; $supProcess = Process::fork($supProcessCallback); usleep(5000 * 1000); $supProcess->terminate(); usleep(5000 * 1000);
<?php /** * @author bigbigant */ require __DIR__ . '/bootstrap.inc.php'; use Comos\Qpm\Process\Process; echo "The program will run in background in 50 seconds.\nYou can see the prints in " . __FILE__ . ".log\n"; //实际的工作内容 function work() { $i = 10; while (--$i) { file_put_contents(__FILE__ . '.log', date('Y-m-d H:i:s') . "\n", FILE_APPEND); sleep(5); } } //通过回调启动子进程 Process::current()->fork(function () { //子进程将自己转入后台 Process::current()->toBackground(); work(); });
/** * worker * * executes in child Process */ function worker() { sleep(5); $msg = sprintf("PID: %d\tPPID:%d\n", Process::current()->getPid(), Process::current()->getParent()->getPid()); file_put_contents(__FILE__ . '.log', $msg, FILE_APPEND); }