public function render()
 {
     $rows = array();
     if (!$this->user) {
         throw new Exception("Call setUser() before rendering!");
     }
     foreach ($this->daemonLogs as $log) {
         $epoch = $log->getDateCreated();
         if ($log->getHost() == php_uname('n')) {
             $pid = $log->getPID();
             $is_running = PhabricatorDaemonReference::isProcessRunning($pid);
             if ($is_running) {
                 $running = phutil_render_tag('span', array('style' => 'color: #00cc00', 'title' => 'Running'), '•');
             } else {
                 $running = phutil_render_tag('span', array('style' => 'color: #cc0000', 'title' => 'Not running'), '•');
             }
         } else {
             $running = phutil_render_tag('span', array('style' => 'color: #888888', 'title' => 'Not on this host'), '?');
         }
         $rows[] = array($running, phutil_escape_html($log->getDaemon()), phutil_escape_html($log->getHost()), $log->getPID(), phabricator_date($epoch, $this->user), phabricator_time($epoch, $this->user), phutil_render_tag('a', array('href' => '/daemon/log/' . $log->getID() . '/', 'class' => 'button small grey'), 'View Log'));
     }
     $daemon_table = new AphrontTableView($rows);
     $daemon_table->setHeaders(array('', 'Daemon', 'Host', 'PID', 'Date', 'Time', 'View'));
     $daemon_table->setColumnClasses(array('', 'wide wrap', '', '', '', 'right', 'action'));
     return $daemon_table->render();
 }
 public function render()
 {
     $rows = array();
     if (!$this->user) {
         throw new Exception("Call setUser() before rendering!");
     }
     foreach ($this->daemonLogs as $log) {
         $epoch = $log->getDateCreated();
         $status = $log->getStatus();
         if ($log->getHost() == php_uname('n') && $status != PhabricatorDaemonLog::STATUS_EXITED && $status != PhabricatorDaemonLog::STATUS_DEAD) {
             $pid = $log->getPID();
             $is_running = PhabricatorDaemonReference::isProcessRunning($pid);
             if (!$is_running) {
                 $guard = AphrontWriteGuard::beginScopedUnguardedWrites();
                 $log->setStatus(PhabricatorDaemonLog::STATUS_DEAD);
                 $log->save();
                 unset($guard);
                 $status = PhabricatorDaemonLog::STATUS_DEAD;
             }
         }
         $heartbeat_timeout = $log->getDateModified() + 3 * PhutilDaemonOverseer::HEARTBEAT_WAIT;
         if ($status == PhabricatorDaemonLog::STATUS_RUNNING && $heartbeat_timeout < time()) {
             $status = PhabricatorDaemonLog::STATUS_UNKNOWN;
         }
         switch ($status) {
             case PhabricatorDaemonLog::STATUS_RUNNING:
                 $style = 'color: #00cc00';
                 $title = 'Running';
                 $symbol = '&bull;';
                 break;
             case PhabricatorDaemonLog::STATUS_DEAD:
                 $style = 'color: #cc0000';
                 $title = 'Died';
                 $symbol = '&bull;';
                 break;
             case PhabricatorDaemonLog::STATUS_EXITED:
                 $style = 'color: #000000';
                 $title = 'Exited';
                 $symbol = '&bull;';
                 break;
             case PhabricatorDaemonLog::STATUS_UNKNOWN:
             default:
                 // fallthrough
                 $style = 'color: #888888';
                 $title = 'Unknown';
                 $symbol = '?';
         }
         $running = phutil_render_tag('span', array('style' => $style, 'title' => $title), $symbol);
         $rows[] = array($running, phutil_escape_html($log->getDaemon()), phutil_escape_html($log->getHost()), $log->getPID(), phabricator_date($epoch, $this->user), phabricator_time($epoch, $this->user), phutil_render_tag('a', array('href' => '/daemon/log/' . $log->getID() . '/', 'class' => 'button small grey'), 'View Log'));
     }
     $daemon_table = new AphrontTableView($rows);
     $daemon_table->setHeaders(array('', 'Daemon', 'Host', 'PID', 'Date', 'Time', 'View'));
     $daemon_table->setColumnClasses(array('', 'wide wrap', '', '', '', 'right', 'action'));
     return $daemon_table->render();
 }
 private function sendSignal(array $pids, $signo, $wait)
 {
     $console = PhutilConsole::getConsole();
     $pids = array_fuse($pids);
     foreach ($pids as $key => $pid) {
         if (!$pid) {
             // NOTE: We must have a PID to signal a daemon, since sending a signal
             // to PID 0 kills this process.
             unset($pids[$key]);
             continue;
         }
         switch ($signo) {
             case SIGINT:
                 $message = pht('Interrupting process %d...', $pid);
                 break;
             case SIGTERM:
                 $message = pht('Terminating process %d...', $pid);
                 break;
             case SIGKILL:
                 $message = pht('Killing process %d...', $pid);
                 break;
         }
         $console->writeOut("%s\n", $message);
         posix_kill($pid, $signo);
     }
     if ($wait) {
         $start = PhabricatorTime::getNow();
         do {
             foreach ($pids as $key => $pid) {
                 if (!PhabricatorDaemonReference::isProcessRunning($pid)) {
                     $console->writeOut(pht('Process %d exited.', $pid) . "\n");
                     unset($pids[$key]);
                 }
             }
             if (empty($pids)) {
                 break;
             }
             usleep(100000);
         } while (PhabricatorTime::getNow() < $start + $wait);
     }
     return $pids;
 }
 public function loadRunningDaemons()
 {
     $results = array();
     $pid_dir = $this->getPIDDirectory();
     $pid_files = Filesystem::listDirectory($pid_dir);
     if (!$pid_files) {
         return $results;
     }
     foreach ($pid_files as $pid_file) {
         $pid_data = Filesystem::readFile($pid_dir . '/' . $pid_file);
         $dict = json_decode($pid_data, true);
         if (!is_array($dict)) {
             // Just return a hanging reference, since control code needs to be
             // robust against unusual system states.
             $dict = array();
         }
         $ref = PhabricatorDaemonReference::newFromDictionary($dict);
         $ref->setPIDFile($pid_dir . '/' . $pid_file);
         $results[] = $ref;
     }
     return $results;
 }
 private function buildRogueDaemons(array $daemons)
 {
     $rogue_daemons = array();
     foreach ($daemons as $pid => $data) {
         $rogue_daemons[] = PhabricatorDaemonReference::newFromRogueDictionary($data);
     }
     return $rogue_daemons;
 }
 protected final function executeStopCommand()
 {
     $console = PhutilConsole::getConsole();
     $pid = $this->getPID();
     if (!$pid) {
         $console->writeErr("%s\n", pht('Aphlict is not running.'));
         return 0;
     }
     $console->writeErr("%s\n", pht('Stopping Aphlict Server (%s)...', $pid));
     posix_kill($pid, SIGINT);
     $start = time();
     do {
         if (!PhabricatorDaemonReference::isProcessRunning($pid)) {
             $console->writeOut("%s\n", pht('Aphlict Server (%s) exited normally.', $pid));
             $pid = null;
             break;
         }
         usleep(100000);
     } while (time() < $start + 5);
     if ($pid) {
         $console->writeErr("%s\n", pht('Sending %s a SIGKILL.', $pid));
         posix_kill($pid, SIGKILL);
         unset($pid);
     }
     Filesystem::remove($this->getPIDPath());
     return 0;
 }