fork() публичный Метод

Forks something into another process and returns a deferred object.
public fork ( $callable )
Пример #1
0
 public function testRunningDaemonWithResistingWorker()
 {
     $writer = $this->getFileWriter();
     $fork = $this->outerManager->fork(function () use($writer) {
         $handler = new NullHandler();
         $builder = new Builder(array('worker1' => function () use($writer) {
             $writer("worker1.call");
         }, 'worker2' => array('startup' => function () use($writer) {
             pcntl_signal(SIGQUIT, SIG_IGN);
             pcntl_signal(SIGINT, SIG_IGN);
             $writer("worker2.startup");
         }, 'loop' => function () use($writer) {
             $writer("worker2.call");
         }, 'interval' => 1)));
         $builder->setLogger(new Logger('test', array($handler)))->setShutdownTimeout(3);
         $daemon = $builder->build();
         $daemon->setProcessName('testing');
         $daemon->run();
     });
     sleep(1);
     $start = time();
     $fork->kill(SIGQUIT);
     while (posix_kill($fork->getPid(), 0)) {
         pcntl_waitpid($fork->getPid(), $status, WNOHANG | WUNTRACED);
         usleep(100000);
     }
     $end = time();
     $diff = $end - $start;
     $this->assertTrue($diff >= 2 && $diff <= 4, 'Has been killed in shutdown interval');
     $content = file_get_contents($this->tempFile);
     $this->assertSame(1, preg_match_all('/worker1\\.call/', $content));
     $this->assertSame(1, preg_match_all('/worker2\\.startup/', $content));
     $calls = preg_match_all('/worker2\\.call/', $content);
     $this->assertTrue($calls >= 3 && $calls <= 5, 'Expected amount of worker2 calls');
 }
Пример #2
0
 public function testObjectReturn()
 {
     $fork = $this->manager->fork(function () {
         return new Unserializable();
     });
     $this->manager->wait();
     $this->assertNull($fork->getResult());
     $this->assertFalse($fork->isSuccessful());
 }
Пример #3
0
 /**
  * Forks, runs code in the children and wait until all finished.
  *
  * @param int $concurrency The amount of forks.
  * @param callable $code The code for the fork.
  */
 private function fork($concurrency, callable $code)
 {
     $manager = new ProcessManager();
     for ($i = 0; $i < $concurrency; $i++) {
         $manager->fork($code);
     }
 }
Пример #4
0
 /**
  * @param Job $job
  * @return \Spork\Fork
  */
 protected function performJob(Job $job)
 {
     $this->host->disconnect();
     return $this->spork->fork(function () use($job) {
         $performer = new JobPerformer($this->host, $job, $this->jobCreator, $this->logger);
         return $performer->perform();
     });
 }
Пример #5
0
 /**
  * Makes sure worker instance is running
  *
  * @param Worker $worker
  */
 protected function assureWorkerForkRunning(Worker $worker)
 {
     // start now required amount
     $self =& $this;
     $name = $worker->getName();
     $diff = $worker->getAmount() - $this->countRunning($name);
     if (!isset($this->forks[$name])) {
         $this->forks[$name] = array();
     }
     for ($i = 0; $i < $diff; $i++) {
         $this->event->dispatch(Event::EVENT_WORKER_STARTING, new Event($worker));
         $fork = $this->manager->fork(function () use($worker, $self) {
             $this->currentWorker = $worker;
             $self->bindWorkerSignals();
             if (function_exists('setproctitle')) {
                 setproctitle($worker->getName());
             }
             $startupArgs = array();
             if ($worker->hasStartup()) {
                 $startupArgs = $worker->runStartup();
                 if (!is_array($startupArgs)) {
                     $startupArgs = array($startupArgs);
                 }
             }
             $intervals = $worker->getInterval() * 10;
             while (true) {
                 $worker->run($startupArgs);
                 for ($i = 0; $i < $intervals; $i++) {
                     Builtin::doUsleep(100000);
                     if ($self->stopped) {
                         $this->event->dispatch(Event::EVENT_WORKER_STOPPED, new Event($this->currentWorker));
                         break 2;
                     }
                 }
             }
         })->then(function (Fork $fork) use($name, $self) {
             unset($self->forks[$fork->getPid()][$name]);
         });
         $this->forks[$name][$fork->getPid()] = $fork;
         $this->event->dispatch(Event::EVENT_WORKER_STARTED, new Event($worker), array($fork));
     }
 }
Пример #6
0
 /**
  * Tests seeding produces different tokens for each process.
  *
  * @test
  */
 public function testSeedRandom()
 {
     $mutex = $this->buildRedisMutex(1);
     $mutex->seedRandom();
     $tokens = [];
     $processManager = new ProcessManager();
     for ($i = 0; $i < 2; $i++) {
         $processManager->fork(function () {
             $mutex = $this->buildRedisMutex(1);
             $mutex->expects($this->any())->method("evalScript")->willReturn(true);
             $token = null;
             $mutex->expects($this->any())->method("add")->willReturnCallback(function ($redisAPI, $key, $value, $expire) use(&$token) {
                 $token = "{$value}";
                 return true;
             });
             $mutex->synchronized(function () {
             });
             return $token;
         })->then(function (Fork $fork) use(&$tokens) {
             $this->assertArrayNotHasKey($fork->getResult(), $tokens);
             $tokens[$fork->getResult()] = $fork->getResult();
         });
     }
 }
Пример #7
0
 /**
  * Tests that locks will be released automatically.
  *
  * @param callable $mutexFactory The Mutex factory.
  * @test
  * @dataProvider provideMutexFactories
  */
 public function testLiveness(callable $mutexFactory)
 {
     $manager = new ProcessManager();
     $manager->fork(function () use($mutexFactory) {
         $mutex = call_user_func($mutexFactory);
         $mutex->synchronized(function () {
             exit;
         });
     });
     $manager->wait();
     sleep(self::TIMEOUT - 1);
     $mutex = call_user_func($mutexFactory);
     $mutex->synchronized(function () {
     });
 }