Changeset View
Changeset View
Standalone View
Standalone View
src/infrastructure/daemon/PhutilDaemonHandle.php
| Show All 10 Lines | final class PhutilDaemonHandle extends Phobject { | ||||
| private $pool; | private $pool; | ||||
| private $properties; | private $properties; | ||||
| private $future; | private $future; | ||||
| private $argv; | private $argv; | ||||
| private $restartAt; | private $restartAt; | ||||
| private $busyEpoch; | private $busyEpoch; | ||||
| private $pid; | |||||
| private $daemonID; | private $daemonID; | ||||
| private $deadline; | private $deadline; | ||||
| private $heartbeat; | private $heartbeat; | ||||
| private $stdoutBuffer; | private $stdoutBuffer; | ||||
| private $shouldRestart = true; | private $shouldRestart = true; | ||||
| private $shouldShutdown; | private $shouldShutdown; | ||||
| private $hibernating = false; | private $hibernating = false; | ||||
| private $shouldSendExitEvent = false; | private $shouldSendExitEvent = false; | ||||
| ▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | $this->dispatchEvent( | ||||
| 'argv' => $this->getCommandLineArguments(), | 'argv' => $this->getCommandLineArguments(), | ||||
| 'explicitArgv' => $this->getDaemonArguments(), | 'explicitArgv' => $this->getDaemonArguments(), | ||||
| )); | )); | ||||
| return $this; | return $this; | ||||
| } | } | ||||
| public function isRunning() { | public function isRunning() { | ||||
| return (bool)$this->future; | return (bool)$this->getFuture(); | ||||
| } | } | ||||
| public function isHibernating() { | public function isHibernating() { | ||||
| return | return | ||||
| !$this->isRunning() && | !$this->isRunning() && | ||||
| !$this->isDone() && | !$this->isDone() && | ||||
| $this->hibernating; | $this->hibernating; | ||||
| } | } | ||||
| Show All 13 Lines | public function wakeFromHibernation() { | ||||
| return $this; | return $this; | ||||
| } | } | ||||
| public function isDone() { | public function isDone() { | ||||
| return (!$this->shouldRestart && !$this->isRunning()); | return (!$this->shouldRestart && !$this->isRunning()); | ||||
| } | } | ||||
| public function getFuture() { | |||||
| return $this->future; | |||||
| } | |||||
| public function update() { | public function update() { | ||||
| if (!$this->isRunning()) { | if (!$this->isRunning()) { | ||||
| if (!$this->shouldRestart) { | if (!$this->shouldRestart) { | ||||
| return; | return; | ||||
| } | } | ||||
| if (!$this->restartAt || (time() < $this->restartAt)) { | if (!$this->restartAt || (time() < $this->restartAt)) { | ||||
| return; | return; | ||||
| } | } | ||||
| if ($this->shouldShutdown) { | if ($this->shouldShutdown) { | ||||
| return; | return; | ||||
| } | } | ||||
| $this->startDaemonProcess(); | $this->startDaemonProcess(); | ||||
| } | } | ||||
| $future = $this->future; | $future = $this->getFuture(); | ||||
| $result = null; | $result = null; | ||||
| if ($future->isReady()) { | $caught = null; | ||||
| if ($future->canResolve()) { | |||||
| $this->future = null; | |||||
| try { | |||||
| $result = $future->resolve(); | $result = $future->resolve(); | ||||
| } catch (Exception $ex) { | |||||
| $caught = $ex; | |||||
| } catch (Throwable $ex) { | |||||
| $caught = $ex; | |||||
| } | |||||
| } | } | ||||
| list($stdout, $stderr) = $future->read(); | list($stdout, $stderr) = $future->read(); | ||||
| $future->discardBuffers(); | $future->discardBuffers(); | ||||
| if (strlen($stdout)) { | if (strlen($stdout)) { | ||||
| $this->didReadStdout($stdout); | $this->didReadStdout($stdout); | ||||
| } | } | ||||
| $stderr = trim($stderr); | $stderr = trim($stderr); | ||||
| if (strlen($stderr)) { | if (strlen($stderr)) { | ||||
| foreach (phutil_split_lines($stderr, false) as $line) { | foreach (phutil_split_lines($stderr, false) as $line) { | ||||
| $this->logMessage('STDE', $line); | $this->logMessage('STDE', $line); | ||||
| } | } | ||||
| } | } | ||||
| if ($result !== null) { | if ($result !== null || $caught !== null) { | ||||
| if ($caught) { | |||||
| $message = pht( | |||||
| 'Process failed with exception: %s', | |||||
| $caught->getMessage()); | |||||
| $this->logMessage('FAIL', $message); | |||||
| } else { | |||||
| list($err) = $result; | list($err) = $result; | ||||
| if ($err) { | if ($err) { | ||||
| $this->logMessage('FAIL', pht('Process exited with error %s.', $err)); | $this->logMessage('FAIL', pht('Process exited with error %s.', $err)); | ||||
| } else { | } else { | ||||
| $this->logMessage('DONE', pht('Process exited normally.')); | $this->logMessage('DONE', pht('Process exited normally.')); | ||||
| } | } | ||||
| } | |||||
| $this->future = null; | |||||
| if ($this->shouldShutdown) { | if ($this->shouldShutdown) { | ||||
| $this->restartAt = null; | $this->restartAt = null; | ||||
| } else { | } else { | ||||
| $this->scheduleRestart(); | $this->scheduleRestart(); | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | final class PhutilDaemonHandle extends Phobject { | ||||
| private function generateDaemonID() { | private function generateDaemonID() { | ||||
| return substr(getmypid().':'.Filesystem::readRandomCharacters(12), 0, 12); | return substr(getmypid().':'.Filesystem::readRandomCharacters(12), 0, 12); | ||||
| } | } | ||||
| public function getDaemonID() { | public function getDaemonID() { | ||||
| return $this->daemonID; | return $this->daemonID; | ||||
| } | } | ||||
| public function getPID() { | private function getFuture() { | ||||
| return $this->pid; | return $this->future; | ||||
| } | |||||
| private function getPID() { | |||||
| $future = $this->getFuture(); | |||||
| if (!$future) { | |||||
| return null; | |||||
| } | |||||
| if (!$future->hasPID()) { | |||||
| return null; | |||||
| } | |||||
| return $future->getPID(); | |||||
| } | } | ||||
| private function getCaptureBufferSize() { | private function getCaptureBufferSize() { | ||||
| return 65535; | return 65535; | ||||
| } | } | ||||
| private function getRequiredHeartbeatFrequency() { | private function getRequiredHeartbeatFrequency() { | ||||
| return 86400; | return 86400; | ||||
| ▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | final class PhutilDaemonHandle extends Phobject { | ||||
| private function startDaemonProcess() { | private function startDaemonProcess() { | ||||
| $this->logMessage('INIT', pht('Starting process.')); | $this->logMessage('INIT', pht('Starting process.')); | ||||
| $this->deadline = time() + $this->getRequiredHeartbeatFrequency(); | $this->deadline = time() + $this->getRequiredHeartbeatFrequency(); | ||||
| $this->heartbeat = time() + self::getHeartbeatEventFrequency(); | $this->heartbeat = time() + self::getHeartbeatEventFrequency(); | ||||
| $this->stdoutBuffer = ''; | $this->stdoutBuffer = ''; | ||||
| $this->hibernating = false; | $this->hibernating = false; | ||||
| $this->future = $this->newExecFuture(); | $future = $this->newExecFuture(); | ||||
| $this->future->start(); | $this->future = $future; | ||||
| $this->pid = $this->future->getPID(); | $pool = $this->getDaemonPool(); | ||||
| $overseer = $pool->getOverseer(); | |||||
| $overseer->addFutureToPool($future); | |||||
| } | } | ||||
| private function didReadStdout($data) { | private function didReadStdout($data) { | ||||
| $this->stdoutBuffer .= $data; | $this->stdoutBuffer .= $data; | ||||
| while (true) { | while (true) { | ||||
| $pos = strpos($this->stdoutBuffer, "\n"); | $pos = strpos($this->stdoutBuffer, "\n"); | ||||
| if ($pos === false) { | if ($pos === false) { | ||||
| break; | break; | ||||
| ▲ Show 20 Lines • Show All 153 Lines • Show Last 20 Lines | |||||