Exemplo n.º 1
0
 protected function configureFuture(ExecFuture $future)
 {
     if ($this->getTimeout()) {
         $future->setTimeout($this->getTimeout());
     }
     if ($this->getByteLimit()) {
         $future->setStdoutSizeLimit($this->getByteLimit());
         $future->setStderrSizeLimit($this->getByteLimit());
     }
 }
 public function loadChangesetsForCommit($identifier)
 {
     $byte_limit = HeraldCommitAdapter::getEnormousByteLimit();
     $time_limit = HeraldCommitAdapter::getEnormousTimeLimit();
     $vcs = $this->getRepository()->getVersionControlSystem();
     switch ($vcs) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
         case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
             // For git and hg, we can use normal commands.
             $drequest = DiffusionRequest::newFromDictionary(array('repository' => $this->getRepository(), 'user' => $this->getViewer(), 'commit' => $identifier));
             $raw_diff = DiffusionRawDiffQuery::newFromDiffusionRequest($drequest)->setTimeout($time_limit)->setByteLimit($byte_limit)->setLinesOfContext(0)->loadRawDiff();
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
             // TODO: This diff has 3 lines of context, which produces slightly
             // incorrect "added file content" and "removed file content" results.
             // This may also choke on binaries, but "svnlook diff" does not support
             // the "--diff-cmd" flag.
             // For subversion, we need to use `svnlook`.
             $future = new ExecFuture('svnlook diff -t %s %s', $this->subversionTransaction, $this->subversionRepository);
             $future->setTimeout($time_limit);
             $future->setStdoutSizeLimit($byte_limit);
             $future->setStderrSizeLimit($byte_limit);
             list($raw_diff) = $future->resolvex();
             break;
         default:
             throw new Exception(pht("Unknown VCS '%s!'", $vcs));
     }
     if (strlen($raw_diff) >= $byte_limit) {
         throw new Exception(pht('The raw text of this change is enormous (larger than %d ' . 'bytes). Herald can not process it.', $byte_limit));
     }
     if (!strlen($raw_diff)) {
         // If the commit is actually empty, just return no changesets.
         return array();
     }
     $parser = new ArcanistDiffParser();
     $changes = $parser->parseDiff($raw_diff);
     $diff = DifferentialDiff::newEphemeralFromRawChanges($changes);
     return $diff->getChangesets();
 }
Exemplo n.º 3
0
 public function run()
 {
     if ($this->shouldRunSilently()) {
         echo "Running daemon '{$this->daemon}' silently. Use '--trace' or " . "'--verbose' to produce debugging output.\n";
     }
     $root = phutil_get_library_root('phutil');
     $root = dirname($root);
     $exec_dir = $root . '/scripts/daemon/exec/';
     // NOTE: PHP implements proc_open() by running 'sh -c'. On most systems this
     // is bash, but on Ubuntu it's dash. When you proc_open() using bash, you
     // get one new process (the command you ran). When you proc_open() using
     // dash, you get two new processes: the command you ran and a parent
     // "dash -c" (or "sh -c") process. This means that the child process's PID
     // is actually the 'dash' PID, not the command's PID. To avoid this, use
     // 'exec' to replace the shell process with the real process; without this,
     // the child will call posix_getppid(), be given the pid of the 'sh -c'
     // process, and send it SIGUSR1 to keepalive which will terminate it
     // immediately. We also won't be able to do process group management because
     // the shell process won't properly posix_setsid() so the pgid of the child
     // won't be meaningful.
     // Format the exec command, which looks something like:
     //
     //   exec ./exec_daemon DaemonName --trace -- --no-discovery
     $argv = array();
     $argv[] = csprintf('exec ./exec_daemon.php %s', $this->daemon);
     foreach ($this->argv as $k => $arg) {
         $argv[] = csprintf('%s', $arg);
     }
     $argv[] = '--';
     foreach ($this->moreArgs as $k => $arg) {
         $argv[] = csprintf('%s', $arg);
     }
     $command = implode(' ', $argv);
     while (true) {
         $this->logMessage('INIT', 'Starting process.');
         $future = new ExecFuture('%C', $command);
         $future->setCWD($exec_dir);
         $future->setStdoutSizeLimit($this->captureBufferSize);
         $future->setStderrSizeLimit($this->captureBufferSize);
         $this->deadline = time() + $this->deadlineTimeout;
         $this->heartbeat = time() + self::HEARTBEAT_WAIT;
         $future->isReady();
         $this->childPID = $future->getPID();
         do {
             do {
                 if ($this->traceMemory) {
                     $memuse = number_format(memory_get_usage() / 1024, 1);
                     $this->logMessage('RAMS', 'Overseer Memory Usage: ' . $memuse . ' KB');
                 }
                 // We need a shortish timeout here so we can run the tick handler
                 // frequently in order to process signals.
                 $result = $future->resolve(1);
                 list($stdout, $stderr) = $future->read();
                 $stdout = trim($stdout);
                 $stderr = trim($stderr);
                 if (strlen($stdout)) {
                     $this->logMessage('STDO', $stdout);
                 }
                 if (strlen($stderr)) {
                     $this->logMessage('STDE', $stderr);
                 }
                 $future->discardBuffers();
                 if ($result !== null) {
                     list($err) = $result;
                     if ($err) {
                         $this->logMessage('FAIL', 'Process exited with error ' . $err . '.', $err);
                     } else {
                         $this->logMessage('DONE', 'Process exited successfully.');
                     }
                     break 2;
                 }
                 if ($this->heartbeat < time()) {
                     $this->heartbeat = time() + self::HEARTBEAT_WAIT;
                     $this->dispatchEvent(self::EVENT_DID_HEARTBEAT);
                 }
             } while (time() < $this->deadline);
             $this->logMessage('HANG', 'Hang detected. Restarting process.');
             $this->annihilateProcessGroup();
         } while (false);
         if ($this->inGracefulShutdown) {
             // If we just exited because of a graceful shutdown, break now.
             break;
         }
         $this->logMessage('WAIT', 'Waiting to restart process.');
         sleep(self::RESTART_WAIT);
         if ($this->inGracefulShutdown) {
             // If we were awakend by a graceful shutdown, break now.
             break;
         }
     }
     // This is a clean exit after a graceful shutdown.
     $this->dispatchEvent(self::EVENT_WILL_EXIT);
     exit(0);
 }
Exemplo n.º 4
0
 public function run()
 {
     if ($this->shouldRunSilently()) {
         echo "Running daemon '{$this->daemon}' silently. Use '--trace' or " . "'--verbose' to produce debugging output.\n";
     }
     $root = phutil_get_library_root('phutil');
     $root = dirname($root);
     $exec_dir = $root . '/scripts/daemon/exec/';
     // NOTE: PHP implements proc_open() by running 'sh -c'. On most systems this
     // is bash, but on Ubuntu it's dash. When you proc_open() using bash, you
     // get one new process (the command you ran). When you proc_open() using
     // dash, you get two new processes: the command you ran and a parent
     // "dash -c" (or "sh -c") process. This means that the child process's PID
     // is actually the 'dash' PID, not the command's PID. To avoid this, use
     // 'exec' to replace the shell process with the real process; without this,
     // the child will call posix_getppid(), be given the pid of the 'sh -c'
     // process, and send it SIGUSR1 to keepalive which will terminate it
     // immediately. We also won't be able to do process group management because
     // the shell process won't properly posix_setsid() so the pgid of the child
     // won't be meaningful.
     $exec_daemon = './exec_daemon.php';
     $argv = $this->argv;
     array_unshift($argv, 'exec', $exec_daemon, $this->daemon);
     foreach ($argv as $k => $arg) {
         $argv[$k] = escapeshellarg($arg);
     }
     $command = implode(' ', $argv);
     while (true) {
         $this->logMessage('INIT', 'Starting process.');
         $future = new ExecFuture($command);
         $future->setCWD($exec_dir);
         $future->setStdoutSizeLimit($this->captureBufferSize);
         $future->setStderrSizeLimit($this->captureBufferSize);
         $this->deadline = time() + $this->deadlineTimeout;
         $this->heartbeat = time() + self::HEARTBEAT_WAIT;
         $future->isReady();
         $this->childPID = $future->getPID();
         do {
             do {
                 if ($this->traceMemory) {
                     $memuse = number_format(memory_get_usage() / 1024, 1);
                     $this->logMessage('RAMS', 'Overseer Memory Usage: ' . $memuse . ' KB');
                 }
                 // We need a shortish timeout here so we can run the tick handler
                 // frequently in order to process signals.
                 $result = $future->resolve(1);
                 list($stdout, $stderr) = $future->read();
                 $stdout = trim($stdout);
                 $stderr = trim($stderr);
                 if (strlen($stdout)) {
                     $this->logMessage('STDO', $stdout, $stdout);
                 }
                 if (strlen($stderr)) {
                     $this->logMessage('STDE', $stderr, $stderr);
                 }
                 $future->discardBuffers();
                 if ($result !== null) {
                     list($err) = $result;
                     if ($err) {
                         $this->logMessage('FAIL', 'Process exited with error ' . $err . '.', $err);
                     } else {
                         $this->logMessage('DONE', 'Process exited successfully.');
                     }
                     break 2;
                 }
                 if ($this->heartbeat < time()) {
                     $this->heartbeat = time() + self::HEARTBEAT_WAIT;
                     if ($this->conduitURI) {
                         try {
                             $this->conduit = new ConduitClient($this->conduitURI);
                             $this->conduit->callMethodSynchronous('daemon.setstatus', array('daemonLogID' => $this->daemonLogID, 'status' => 'run'));
                         } catch (Exception $ex) {
                         }
                     }
                 }
             } while (time() < $this->deadline);
             $this->logMessage('HANG', 'Hang detected. Restarting process.');
             $this->annihilateProcessGroup();
         } while (false);
         $this->logMessage('WAIT', 'Waiting to restart process.');
         sleep($this->restartDelay);
     }
 }
 protected final function launch()
 {
     $console = PhutilConsole::getConsole();
     if ($this->debug) {
         $console->writeOut("%s\n", pht('Starting Aphlict server in foreground...'));
     } else {
         Filesystem::writeFile($this->getPIDPath(), getmypid());
     }
     $command = $this->getStartCommand($this->getServerArgv());
     if (!$this->debug) {
         declare (ticks=1);
         pcntl_signal(SIGINT, array($this, 'cleanup'));
         pcntl_signal(SIGTERM, array($this, 'cleanup'));
     }
     register_shutdown_function(array($this, 'cleanup'));
     if ($this->debug) {
         $console->writeOut("%s\n\n    \$ %s\n\n", pht('Launching server:'), $command);
         $err = phutil_passthru('%C', $command);
         $console->writeOut(">>> %s\n", pht('Server exited!'));
         exit($err);
     } else {
         while (true) {
             global $g_future;
             $g_future = new ExecFuture('exec %C', $command);
             // Discard all output the subprocess produces: it writes to the log on
             // disk, so we don't need to send the output anywhere and can just
             // throw it away.
             $g_future->setStdoutSizeLimit(0)->setStderrSizeLimit(0);
             $g_future->resolve();
             // If the server exited, wait a couple of seconds and restart it.
             unset($g_future);
             sleep(2);
         }
     }
 }