/** * Creates a log (output). * * @param string $event * @param Control $control * @param boolean $output * @return void */ protected function log($event, Control $control, $output) { $record = array('date' => date('Y-m-d H:i:s'), 'pid' => $control->info()->getId(), 'actionId' => $this->actionId, 'event' => $event); $this->records[] = $record; if (!$output) { return; } $message = sprintf('[%s] PID: %d, Id: %d, Event: %s', $record['date'], $record['pid'], $record['actionId'], $record['event']); echo $message . PHP_EOL; }
/** * {@inheritdoc} */ public function wait() { if (!is_null($this->status)) { return false; } $waitStatus = 0; $waitReturn = $this->control->waitProcessId($this->getId(), $waitStatus); if ($waitReturn === $this->getId()) { $this->context->isRunning = false; $this->context->processId = null; } $this->status = new Status($waitStatus); return -1 !== $waitReturn; }
/** * Initializes pidfile. * * Create an empty file, store the PID into the file and lock it. */ public function initialize() { if ($this->isActive()) { throw new RuntimeException('Process is already active'); } $handle = $this->getFileResource(); if (!@flock($handle, LOCK_EX | LOCK_NB)) { throw new RuntimeException('Could not lock pidfile'); } if (-1 === @fseek($handle, 0)) { throw new RuntimeException('Could not seek pidfile cursor'); } if (!@ftruncate($handle, 0)) { throw new RuntimeException('Could not truncate pidfile'); } if (!@fwrite($handle, $this->control->info()->getId() . PHP_EOL)) { throw new RuntimeException('Could not write on pidfile'); } }
public function testShouldCollectExistingGarbageCyclesOnFlushMethod() { $actualCount = 0; $expectedCount = 1; $this->overwrite('gc_collect_cycles', function () use(&$actualCount) { $actualCount++; }); $control = new Control(); $control->flush(); $this->assertSame($expectedCount, $actualCount); }
<?php declare (ticks=1); require_once __DIR__ . '/../vendor/autoload.php'; use Arara\Process\Action\Callback; use Arara\Process\Child; use Arara\Process\Control; $control = new Control(); $child = new Child(new Callback(function (Control $control) { echo 'This child process will sleep for 5 seconds' . PHP_EOL; $control->flush(5); echo 'This child just woke up' . PHP_EOL; }), $control); $child->start(); $control->flush(0.5); if ($child->isRunning()) { echo 'Child is running' . PHP_EOL; } $child->terminate(); if (!$child->isRunning()) { echo 'Child was terminated' . PHP_EOL; }
<?php declare (ticks=1); require_once __DIR__ . '/../vendor/autoload.php'; use Arara\Process\Action\Callback; use Arara\Process\Child; use Arara\Process\Control; $control = new Control(); $child = new Child(new Callback(function (Control $control) { echo 'Child process is ' . $control->info()->getId() . PHP_EOL; $control->flush(1); }), $control); echo 'Parent process is ' . $control->info()->getId() . PHP_EOL; $child->start(); if ($child->getStatus()->isSuccessful()) { echo 'Child successfully finished' . PHP_EOL; }
/** * Flash Control * @param number $seconds */ public function flush($seconds = 0) { $this->control->flush($seconds); }
<?php declare (ticks=1); require_once __DIR__ . '/../vendor/autoload.php'; use Arara\Process\Control; use Arara\Process\Pidfile; $control = new Control(); $pidfile = new Pidfile($control, 'myapp', __DIR__); try { $pidfile->initialize(); echo 'Will sleep for 10 seconds, try to run it in another terminal' . PHP_EOL; $control->flush(10); $pidfile->finalize(); // You may use register_shutdown_function([$pidfile, 'finalize']); } catch (Exception $exception) { echo $exception->getMessage() . PHP_EOL; echo 'Running PID is #' . $pidfile->getProcessId() . PHP_EOL; } echo 'Finished' . PHP_EOL;
/** * Default trigger for EVENT_START. * * - Activates the circular reference collector * - Detach session * - Reset umask * - Update work directory * - Close file descriptors * - Define process owner, if any * - Define process group, if any * - Create new file descriptors * - Create pidfile * - Define pidfile cleanup * * @param Control $control * @param Context $context */ public function handleStart(Control $control, Context $context) { if (!$context->pidfile instanceof Pidfile) { throw new LogicException('Pidfile is not defined'); } // Activates the circular reference collector gc_enable(); // Callback for handle when process is terminated $control->signal()->prependHandler(SIGTERM, function () use($context) { $this->setAsDying(); $context->pidfile->finalize(); }); $control->signal()->setHandler(SIGTSTP, SIG_IGN); $control->signal()->setHandler(SIGTTOU, SIG_IGN); $control->signal()->setHandler(SIGTTIN, SIG_IGN); $control->signal()->setHandler(SIGHUP, SIG_IGN); // Detach session $control->info()->detachSession(); // Reset umask @umask($this->getOption('umask')); // Update work directory @chdir($this->getOption('work_dir')); // Close file descriptors fclose(STDIN); fclose(STDOUT); fclose(STDERR); // Define process owner if (null !== ($userId = $this->getOption('user_id'))) { $control->info()->setUserId($userId); } // Define process group if (null !== ($groupId = $this->getOption('group_id'))) { $control->info()->setGroupId($groupId); } // Create new file descriptors $context->stdin = fopen($this->getOption('stdin'), 'r'); $context->stdout = fopen($this->getOption('stdout'), 'wb'); $context->stderr = fopen($this->getOption('stderr'), 'wb'); // Create pidfile $context->pidfile->initialize(); }