[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/infrastructure/daemon/control/ -> PhabricatorDaemonReference.php (source)

   1  <?php
   2  
   3  final class PhabricatorDaemonReference {
   4  
   5    private $name;
   6    private $argv;
   7    private $pid;
   8    private $start;
   9    private $pidFile;
  10  
  11    private $daemonLog;
  12  
  13    public static function newFromFile($path) {
  14      $pid_data = Filesystem::readFile($path);
  15  
  16      try {
  17        $dict = phutil_json_decode($pid_data);
  18      } catch (PhutilJSONParserException $ex) {
  19        $dict = array();
  20      }
  21  
  22      $ref = self::newFromDictionary($dict);
  23      $ref->pidFile = $path;
  24      return $ref;
  25    }
  26  
  27    public static function newFromDictionary(array $dict) {
  28      $ref = new PhabricatorDaemonReference();
  29  
  30      $ref->name  = idx($dict, 'name', 'Unknown');
  31      $ref->argv  = idx($dict, 'argv', array());
  32      $ref->pid   = idx($dict, 'pid');
  33      $ref->start = idx($dict, 'start');
  34  
  35      $ref->daemonLog = id(new PhabricatorDaemonLog())->loadOneWhere(
  36        'daemon = %s AND pid = %d AND dateCreated = %d',
  37        $ref->name,
  38        $ref->pid,
  39        $ref->start);
  40  
  41      return $ref;
  42    }
  43  
  44    /**
  45     * Appropriate for getting @{class:PhabricatorDaemonReference} objects from
  46     * the data from @{class:PhabricatorDaemonManagementWorkflow}'s method
  47     * @{method:findRunningDaemons}.
  48     *
  49     * NOTE: the objects are not fully featured and should be used with caution.
  50     */
  51    public static function newFromRogueDictionary(array $dict) {
  52      $ref = new PhabricatorDaemonReference();
  53      $ref->name = pht('Rogue %s', idx($dict, 'type'));
  54      $ref->pid = idx($dict, 'pid');
  55  
  56      return $ref;
  57    }
  58  
  59    public function updateStatus($new_status) {
  60      try {
  61        if (!$this->daemonLog) {
  62          $this->daemonLog = id(new PhabricatorDaemonLog())->loadOneWhere(
  63            'daemon = %s AND pid = %d AND dateCreated = %d',
  64            $this->name,
  65            $this->pid,
  66            $this->start);
  67        }
  68  
  69        if ($this->daemonLog) {
  70          $this->daemonLog
  71            ->setStatus($new_status)
  72            ->save();
  73        }
  74      } catch (AphrontQueryException $ex) {
  75        // Ignore anything that goes wrong here. We anticipate at least two
  76        // specific failure modes:
  77        //
  78        //   - Upgrade scripts which run `git pull`, then `phd stop`, then
  79        //     `bin/storage upgrade` will fail when trying to update the `status`
  80        //     column, as it does not exist yet.
  81        //   - Daemons running on machines which do not have access to MySQL
  82        //     (like an IRC bot) will not be able to load or save the log.
  83        //
  84        //
  85      }
  86    }
  87  
  88    public function getPID() {
  89      return $this->pid;
  90    }
  91  
  92    public function getName() {
  93      return $this->name;
  94    }
  95  
  96    public function getArgv() {
  97      return $this->argv;
  98    }
  99  
 100    public function getEpochStarted() {
 101      return $this->start;
 102    }
 103  
 104    public function getPIDFile() {
 105      return $this->pidFile;
 106    }
 107  
 108    public function getDaemonLog() {
 109      return $this->daemonLog;
 110    }
 111  
 112    public function isRunning() {
 113      return self::isProcessRunning($this->getPID());
 114    }
 115  
 116    public static function isProcessRunning($pid) {
 117      if (!$pid) {
 118        return false;
 119      }
 120  
 121      if (function_exists('posix_kill')) {
 122        // This may fail if we can't signal the process because we are running as
 123        // a different user (for example, we are 'apache' and the process is some
 124        // other user's, or we are a normal user and the process is root's), but
 125        // we can check the error code to figure out if the process exists.
 126        $is_running = posix_kill($pid, 0);
 127        if (posix_get_last_error() == 1) {
 128          // "Operation Not Permitted", indicates that the PID exists. If it
 129          // doesn't, we'll get an error 3 ("No such process") instead.
 130          $is_running = true;
 131        }
 132      } else {
 133        // If we don't have the posix extension, just exec.
 134        list($err) = exec_manual('ps %s', $pid);
 135        $is_running = ($err == 0);
 136      }
 137  
 138      return $is_running;
 139    }
 140  
 141    public function waitForExit($seconds) {
 142      $start = time();
 143      while (time() < $start + $seconds) {
 144        usleep(100000);
 145        if (!$this->isRunning()) {
 146          return true;
 147        }
 148      }
 149      return !$this->isRunning();
 150    }
 151  
 152  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1