diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 3708f83d02..adc19febba 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -10,7 +10,7 @@ return array( 'conpherence.pkg.css' => '3c8a0668', 'conpherence.pkg.js' => '020aebcf', 'core.pkg.css' => 'af983028', - 'core.pkg.js' => '8225dc58', + 'core.pkg.js' => '5a792749', 'differential.pkg.css' => '8d8360fb', 'differential.pkg.js' => '67e02996', 'diffusion.pkg.css' => '42c75c37', @@ -253,7 +253,7 @@ return array( 'rsrc/externals/javelin/lib/URI.js' => '2e255291', 'rsrc/externals/javelin/lib/Vector.js' => 'e9c80beb', 'rsrc/externals/javelin/lib/WebSocket.js' => 'fdc13e4e', - 'rsrc/externals/javelin/lib/Workflow.js' => '851f642d', + 'rsrc/externals/javelin/lib/Workflow.js' => '445e21a8', 'rsrc/externals/javelin/lib/__tests__/Cookie.js' => 'ca686f71', 'rsrc/externals/javelin/lib/__tests__/DOM.js' => '4566e249', 'rsrc/externals/javelin/lib/__tests__/JSON.js' => '710377ae', @@ -752,7 +752,7 @@ return array( 'javelin-workboard-header' => '111bfd2d', 'javelin-workboard-header-template' => 'ebe83a6b', 'javelin-workboard-order-template' => '03e8891f', - 'javelin-workflow' => '851f642d', + 'javelin-workflow' => '445e21a8', 'maniphest-report-css' => '3d53188b', 'maniphest-task-edit-css' => '272daa84', 'maniphest-task-summary-css' => '61d1667e', @@ -1294,6 +1294,17 @@ return array( '43bc9360' => array( 'javelin-install', ), + '445e21a8' => array( + 'javelin-stratcom', + 'javelin-request', + 'javelin-dom', + 'javelin-vector', + 'javelin-install', + 'javelin-util', + 'javelin-mask', + 'javelin-uri', + 'javelin-routable', + ), '46116c01' => array( 'javelin-request', 'javelin-behavior', @@ -1607,17 +1618,6 @@ return array( 'javelin-resource', 'javelin-routable', ), - '851f642d' => array( - 'javelin-stratcom', - 'javelin-request', - 'javelin-dom', - 'javelin-vector', - 'javelin-install', - 'javelin-util', - 'javelin-mask', - 'javelin-uri', - 'javelin-routable', - ), '87428eb2' => array( 'javelin-behavior', 'javelin-diffusion-locate-file-source', diff --git a/src/applications/config/check/PhabricatorExtraConfigSetupCheck.php b/src/applications/config/check/PhabricatorExtraConfigSetupCheck.php index a8a883ca96..d863c928b7 100644 --- a/src/applications/config/check/PhabricatorExtraConfigSetupCheck.php +++ b/src/applications/config/check/PhabricatorExtraConfigSetupCheck.php @@ -536,6 +536,9 @@ final class PhabricatorExtraConfigSetupCheck extends PhabricatorSetupCheck { 'differential.whitespace-matters' => pht( 'Whitespace rendering is now handled automatically.'), + + 'phd.pid-directory' => pht( + 'Phabricator daemons no longer use PID files.'), ); return $ancient_config; diff --git a/src/applications/config/option/PhabricatorPHDConfigOptions.php b/src/applications/config/option/PhabricatorPHDConfigOptions.php index e04353876a..7a1d39e617 100644 --- a/src/applications/config/option/PhabricatorPHDConfigOptions.php +++ b/src/applications/config/option/PhabricatorPHDConfigOptions.php @@ -21,10 +21,6 @@ final class PhabricatorPHDConfigOptions public function getOptions() { return array( - $this->newOption('phd.pid-directory', 'string', '/var/tmp/phd/pid') - ->setLocked(true) - ->setDescription( - pht('Directory that phd should use to track running daemons.')), $this->newOption('phd.log-directory', 'string', '/var/tmp/phd/log') ->setLocked(true) ->setDescription( diff --git a/src/applications/daemon/management/PhabricatorDaemonManagementRestartWorkflow.php b/src/applications/daemon/management/PhabricatorDaemonManagementRestartWorkflow.php index 3e9f0af8c3..eb2d5d229c 100644 --- a/src/applications/daemon/management/PhabricatorDaemonManagementRestartWorkflow.php +++ b/src/applications/daemon/management/PhabricatorDaemonManagementRestartWorkflow.php @@ -6,7 +6,10 @@ final class PhabricatorDaemonManagementRestartWorkflow protected function didConstruct() { $this ->setName('restart') - ->setSynopsis(pht('Stop, then start the standard daemon loadout.')) + ->setSynopsis( + pht( + 'Stop daemon processes on this host, then start the standard '. + 'daemon loadout.')) ->setArguments( array( array( @@ -17,17 +20,15 @@ final class PhabricatorDaemonManagementRestartWorkflow 'seconds. Defaults to __15__ seconds.'), 'default' => 15, ), - array( - 'name' => 'gently', - 'help' => pht( - 'Ignore running processes that look like daemons but do not '. - 'have corresponding PID files.'), - ), array( 'name' => 'force', 'help' => pht( - 'Also stop running processes that look like daemons but do '. - 'not have corresponding PID files.'), + 'Stop all daemon processes on this host, even if they belong '. + 'to another Phabricator instance.'), + ), + array( + 'name' => 'gently', + 'help' => pht('Deprecated. Has no effect.'), ), $this->getAutoscaleReserveArgument(), )); @@ -35,12 +36,11 @@ final class PhabricatorDaemonManagementRestartWorkflow public function execute(PhutilArgumentParser $args) { $err = $this->executeStopCommand( - array(), array( 'graceful' => $args->getArg('graceful'), 'force' => $args->getArg('force'), - 'gently' => $args->getArg('gently'), )); + if ($err) { return $err; } diff --git a/src/applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php b/src/applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php index 343e42ba63..1f7ed951cb 100644 --- a/src/applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php +++ b/src/applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php @@ -6,101 +6,52 @@ final class PhabricatorDaemonManagementStatusWorkflow protected function didConstruct() { $this ->setName('status') - ->setSynopsis(pht('Show status of running daemons.')) - ->setArguments( - array( - array( - 'name' => 'local', - 'help' => pht('Show only local daemons.'), - ), - )); + ->setSynopsis(pht('Show daemon processes on this host.')); } public function execute(PhutilArgumentParser $args) { - $console = PhutilConsole::getConsole(); + $process_refs = $this->getOverseerProcessRefs(); - if ($args->getArg('local')) { - $daemons = $this->loadRunningDaemons(); - } else { - $daemons = $this->loadAllRunningDaemons(); - } + if (!$process_refs) { + $instance = $this->getInstance(); + if ($instance !== null) { + $this->logInfo( + pht('NO DAEMONS'), + pht( + 'There are no running daemon processes for the current '. + 'instance ("%s").', + $instance)); + } else { + $this->writeInfo( + pht('NO DAEMONS'), + pht('There are no running daemon processes.')); + } - if (!$daemons) { - $console->writeErr( - "%s\n", - pht('There are no running Phabricator daemons.')); return 1; } - $status = 0; - $table = id(new PhutilConsoleTable()) - ->addColumns(array( - 'id' => array( - 'title' => pht('Log'), - ), - 'daemonID' => array( - 'title' => pht('Daemon'), - ), - 'host' => array( - 'title' => pht('Host'), - ), - 'pid' => array( - 'title' => pht('Overseer'), - ), - 'started' => array( - 'title' => pht('Started'), - ), - 'daemon' => array( - 'title' => pht('Class'), - ), - 'argv' => array( - 'title' => pht('Arguments'), - ), - )); - - foreach ($daemons as $daemon) { - if ($daemon instanceof PhabricatorDaemonLog) { - $table->addRow(array( - 'id' => $daemon->getID(), - 'daemonID' => $daemon->getDaemonID(), - 'host' => $daemon->getHost(), - 'pid' => $daemon->getPID(), - 'started' => date('M j Y, g:i:s A', $daemon->getDateCreated()), - 'daemon' => $daemon->getDaemon(), - 'argv' => csprintf('%LR', $daemon->getExplicitArgv()), + ->addColumns( + array( + 'pid' => array( + 'title' => pht('PID'), + ), + 'command' => array( + 'title' => pht('Command'), + ), )); - } else if ($daemon instanceof PhabricatorDaemonReference) { - $name = $daemon->getName(); - if (!$daemon->isRunning()) { - $daemon->updateStatus(PhabricatorDaemonLog::STATUS_DEAD); - $status = 2; - $name = pht(' %s', $name); - } - $daemon_log = $daemon->getDaemonLog(); - $id = null; - $daemon_id = null; - if ($daemon_log) { - $id = $daemon_log->getID(); - $daemon_id = $daemon_log->getDaemonID(); - } - - $table->addRow(array( - 'id' => $id, - 'daemonID' => $daemon_id, - 'host' => 'localhost', - 'pid' => $daemon->getPID(), - 'started' => $daemon->getEpochStarted() - ? date('M j Y, g:i:s A', $daemon->getEpochStarted()) - : null, - 'daemon' => $name, - 'argv' => csprintf('%LR', $daemon->getArgv()), + foreach ($process_refs as $process_ref) { + $table->addRow( + array( + 'pid' => $process_ref->getPID(), + 'command' => $process_ref->getCommand(), )); - } } $table->draw(); + + return 0; } } diff --git a/src/applications/daemon/management/PhabricatorDaemonManagementStopWorkflow.php b/src/applications/daemon/management/PhabricatorDaemonManagementStopWorkflow.php index c54a7e9fee..19b9fc44fb 100644 --- a/src/applications/daemon/management/PhabricatorDaemonManagementStopWorkflow.php +++ b/src/applications/daemon/management/PhabricatorDaemonManagementStopWorkflow.php @@ -6,11 +6,7 @@ final class PhabricatorDaemonManagementStopWorkflow protected function didConstruct() { $this ->setName('stop') - ->setSynopsis( - pht( - 'Stop all running daemons, or specific daemons identified by PIDs. '. - 'Use **%s** to find PIDs.', - 'phd status')) + ->setSynopsis(pht('Stop daemon processes on this host.')) ->setArguments( array( array( @@ -24,29 +20,21 @@ final class PhabricatorDaemonManagementStopWorkflow array( 'name' => 'force', 'help' => pht( - 'Also stop running processes that look like daemons but do '. - 'not have corresponding PID files.'), + 'Stop all daemon processes on this host, even if they belong '. + 'to another Phabricator instance.'), ), array( 'name' => 'gently', - 'help' => pht( - 'Ignore running processes that look like daemons but do not '. - 'have corresponding PID files.'), - ), - array( - 'name' => 'pids', - 'wildcard' => true, + 'help' => pht('Deprecated. Has no effect.'), ), )); } public function execute(PhutilArgumentParser $args) { return $this->executeStopCommand( - $args->getArg('pids'), array( 'graceful' => $args->getArg('graceful'), 'force' => $args->getArg('force'), - 'gently' => $args->getArg('gently'), )); } diff --git a/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php b/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php index d5b4ed23e5..05d94e218d 100644 --- a/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php +++ b/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php @@ -12,11 +12,6 @@ abstract class PhabricatorDaemonManagementWorkflow ->selectSymbolsWithoutLoading(); } - final protected function getPIDDirectory() { - $path = PhabricatorEnv::getEnvConfig('phd.pid-directory'); - return $this->getControlDirectory($path); - } - final protected function getLogDirectory() { $path = PhabricatorEnv::getEnvConfig('phd.log-directory'); return $this->getControlDirectory($path); @@ -30,56 +25,16 @@ abstract class PhabricatorDaemonManagementWorkflow pht( "%s requires the directory '%s' to exist, but it does not exist ". "and could not be created. Create this directory or update ". - "'%s' / '%s' in your configuration to point to an existing ". + "'%s' in your configuration to point to an existing ". "directory.", 'phd', $path, - 'phd.pid-directory', 'phd.log-directory')); } } return $path; } - final protected function loadRunningDaemons() { - $daemons = array(); - - $pid_dir = $this->getPIDDirectory(); - $pid_files = Filesystem::listDirectory($pid_dir); - - foreach ($pid_files as $pid_file) { - $path = $pid_dir.'/'.$pid_file; - $daemons[] = PhabricatorDaemonReference::loadReferencesFromFile($path); - } - - return array_mergev($daemons); - } - - final protected function loadAllRunningDaemons() { - $local_daemons = $this->loadRunningDaemons(); - - $local_ids = array(); - foreach ($local_daemons as $daemon) { - $daemon_log = $daemon->getDaemonLog(); - - if ($daemon_log) { - $local_ids[] = $daemon_log->getID(); - } - } - - $daemon_query = id(new PhabricatorDaemonLogQuery()) - ->setViewer(PhabricatorUser::getOmnipotentUser()) - ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE); - - if ($local_ids) { - $daemon_query->withoutIDs($local_ids); - } - - $remote_daemons = $daemon_query->execute(); - - return array_merge($local_daemons, $remote_daemons); - } - private function findDaemonClass($substring) { $symbols = $this->loadAvailableDaemonClasses(); @@ -169,7 +124,7 @@ abstract class PhabricatorDaemonManagementWorkflow $flags[] = '--verbose'; } - $instance = PhabricatorEnv::getEnvConfig('cluster.instance'); + $instance = $this->getInstance(); if ($instance) { $flags[] = '-l'; $flags[] = $instance; @@ -185,14 +140,6 @@ abstract class PhabricatorDaemonManagementWorkflow $config['log'] = $this->getLogDirectory().'/daemons.log'; } - $pid_dir = $this->getPIDDirectory(); - - // TODO: This should be a much better user experience. - Filesystem::assertExists($pid_dir); - Filesystem::assertIsDirectory($pid_dir); - Filesystem::assertWritable($pid_dir); - - $config['piddir'] = $pid_dir; $config['daemons'] = $daemons; $command = csprintf('./phd-daemon %Ls', $flags); @@ -324,28 +271,31 @@ abstract class PhabricatorDaemonManagementWorkflow $console = PhutilConsole::getConsole(); if (!idx($options, 'force')) { - $running = $this->loadRunningDaemons(); + $process_refs = $this->getOverseerProcessRefs(); + if ($process_refs) { + $this->logWarn( + pht('RUNNING DAEMONS'), + pht('Daemons are already running:')); - // This may include daemons which were launched but which are no longer - // running; check that we actually have active daemons before failing. - foreach ($running as $daemon) { - if ($daemon->isRunning()) { - $message = pht( - "phd start: Unable to start daemons because daemons are already ". - "running.\n\n". - "You can view running daemons with '%s'.\n". - "You can stop running daemons with '%s'.\n". - "You can use '%s' to stop all daemons before starting ". - "new daemons.\n". - "You can force daemons to start anyway with %s.", - 'phd status', - 'phd stop', - 'phd restart', - '--force'); - - $console->writeErr("%s\n", $message); - exit(1); + fprintf(STDERR, '%s', "\n"); + foreach ($process_refs as $process_ref) { + fprintf( + STDERR, + '%s', + tsprintf( + " %s %s\n", + $process_ref->getPID(), + $process_ref->getCommand())); } + fprintf(STDERR, '%s', "\n"); + + $this->logFail( + pht('RUNNING DAEMONS'), + pht( + 'Use "phd stop" to stop daemons, "phd restart" to restart '. + 'daemons, or "phd start --force" to ignore running processes.')); + + exit(1); } } @@ -386,148 +336,115 @@ abstract class PhabricatorDaemonManagementWorkflow return 0; } - final protected function executeStopCommand( - array $pids, - array $options) { - - $console = PhutilConsole::getConsole(); - + final protected function executeStopCommand(array $options) { $grace_period = idx($options, 'graceful', 15); $force = idx($options, 'force'); - $gently = idx($options, 'gently'); - if ($gently && $force) { - throw new PhutilArgumentUsageException( + $query = id(new PhutilProcessQuery()) + ->withIsOverseer(true); + + $instance = $this->getInstance(); + if ($instance !== null && !$force) { + $query->withInstances(array($instance)); + } + + try { + $process_refs = $query->execute(); + } catch (Exception $ex) { + // See T13321. If this fails for some reason, just continue for now so + // that daemon management still works. In the long run, we don't expect + // this to fail, but I don't want to break this workflow while we iron + // bugs out. + + // See T12827. Particularly, this is likely to fail on Solaris. + + phlog($ex); + + $process_refs = array(); + } + + if (!$process_refs) { + if ($instance !== null && !$force) { + $this->logInfo( + pht('NO DAEMONS'), + pht( + 'There are no running daemons for the current instance ("%s"). '. + 'Use "--force" to stop daemons for all instances.', + $instance)); + } else { + $this->logInfo( + pht('NO DAEMONS'), + pht('There are no running daemons.')); + } + + return 0; + } + + $process_refs = mpull($process_refs, null, 'getPID'); + + $stop_pids = array_keys($process_refs); + $live_pids = $this->sendStopSignals($stop_pids, $grace_period); + + $stop_pids = array_fuse($stop_pids); + $live_pids = array_fuse($live_pids); + + $dead_pids = array_diff_key($stop_pids, $live_pids); + + foreach ($dead_pids as $dead_pid) { + $dead_ref = $process_refs[$dead_pid]; + $this->logOkay( + pht('STOP'), pht( - 'You can not specify conflicting options %s and %s together.', - '--gently', - '--force')); + 'Stopped PID %d ("%s")', + $dead_pid, + $dead_ref->getCommand())); } - $daemons = $this->loadRunningDaemons(); - if (!$daemons) { - $survivors = array(); - if (!$pids && !$gently) { - $survivors = $this->processRogueDaemons( - $grace_period, - $warn = true, - $force); - } - if (!$survivors) { - $console->writeErr( - "%s\n", - pht('There are no running Phabricator daemons.')); - } - return 0; + foreach ($live_pids as $live_pid) { + $live_ref = $process_refs[$live_pid]; + $this->logFail( + pht('SURVIVED'), + pht( + 'Unable to stop PID %d ("%s").', + $live_pid, + $live_ref->getCommand())); } - $stop_pids = $this->selectDaemonPIDs($daemons, $pids); - - if (!$stop_pids) { - $console->writeErr("%s\n", pht('No daemons to kill.')); - return 0; - } - - $survivors = $this->sendStopSignals($stop_pids, $grace_period); - - // Try to clean up PID files for daemons we killed. - $remove = array(); - foreach ($daemons as $daemon) { - $pid = $daemon->getPID(); - if (empty($stop_pids[$pid])) { - // We did not try to stop this overseer. - continue; - } - - if (isset($survivors[$pid])) { - // We weren't able to stop this overseer. - continue; - } - - if (!$daemon->getPIDFile()) { - // We don't know where the PID file is. - continue; - } - - $remove[] = $daemon->getPIDFile(); - } - - foreach (array_unique($remove) as $remove_file) { - Filesystem::remove($remove_file); - } - - if (!$gently) { - $this->processRogueDaemons($grace_period, !$pids, $force); + if ($live_pids) { + $this->logWarn( + pht('SURVIVORS'), + pht( + 'Unable to stop all daemon processes. You may need to run this '. + 'command as root with "sudo".')); } return 0; } final protected function executeReloadCommand(array $pids) { - $console = PhutilConsole::getConsole(); + $process_refs = $this->getOverseerProcessRefs(); + + if (!$process_refs) { + $this->logInfo( + pht('NO DAEMONS'), + pht('There are no running daemon processes to reload.')); - $daemons = $this->loadRunningDaemons(); - if (!$daemons) { - $console->writeErr( - "%s\n", - pht('There are no running daemons to reload.')); return 0; } - $reload_pids = $this->selectDaemonPIDs($daemons, $pids); - if (!$reload_pids) { - $console->writeErr( - "%s\n", - pht('No daemons to reload.')); - return 0; - } + foreach ($process_refs as $process_ref) { + $pid = $process_ref->getPID(); - foreach ($reload_pids as $pid) { - $console->writeOut( - "%s\n", + $this->logInfo( + pht('RELOAD'), pht('Reloading process %d...', $pid)); + posix_kill($pid, SIGHUP); } return 0; } - private function processRogueDaemons($grace_period, $warn, $force_stop) { - $console = PhutilConsole::getConsole(); - - $rogue_daemons = PhutilDaemonOverseer::findRunningDaemons(); - if ($rogue_daemons) { - if ($force_stop) { - $rogue_pids = ipull($rogue_daemons, 'pid'); - $survivors = $this->sendStopSignals($rogue_pids, $grace_period); - if ($survivors) { - $console->writeErr( - "%s\n", - pht( - 'Unable to stop processes running without PID files. '. - 'Try running this command again with sudo.')); - } - } else if ($warn) { - $console->writeErr("%s\n", $this->getForceStopHint($rogue_daemons)); - } - } - - return $rogue_daemons; - } - - private function getForceStopHint($rogue_daemons) { - $debug_output = ''; - foreach ($rogue_daemons as $rogue) { - $debug_output .= $rogue['pid'].' '.$rogue['command']."\n"; - } - return pht( - "There are processes running that look like Phabricator daemons but ". - "have no corresponding PID files:\n\n%s\n\n". - "Stop these processes by re-running this command with the %s parameter.", - $debug_output, - '--force'); - } - private function sendStopSignals($pids, $grace_period) { // If we're doing a graceful shutdown, try SIGINT first. if ($grace_period) { @@ -674,4 +591,21 @@ abstract class PhabricatorDaemonManagementWorkflow return $select_pids; } + protected function getOverseerProcessRefs() { + $query = id(new PhutilProcessQuery()) + ->withIsOverseer(true); + + $instance = PhabricatorEnv::getEnvConfig('cluster.instance'); + if ($instance !== null) { + $query->withInstances(array($instance)); + } + + return $query->execute(); + } + + protected function getInstance() { + return PhabricatorEnv::getEnvConfig('cluster.instance'); + } + + } diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php index 775d59d4db..7c327393f8 100644 --- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php @@ -1375,16 +1375,16 @@ abstract class PhabricatorApplicationTransaction public function getActionStrength() { if ($this->isInlineCommentTransaction()) { - return 250; + return 25; } switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_COMMENT: - return 500; + return 50; case PhabricatorTransactions::TYPE_SUBSCRIBERS: if ($this->isSelfSubscription()) { // Make this weaker than TYPE_COMMENT. - return 250; + return 25; } if ($this->isApplicationAuthor()) { @@ -1396,14 +1396,14 @@ abstract class PhabricatorApplicationTransaction // In other cases, subscriptions are more interesting than comments // (which are shown anyway) but less interesting than any other type of // transaction. - return 750; + return 75; case PhabricatorTransactions::TYPE_MFA: // We want MFA signatures to render at the top of transaction groups, // on top of the things they signed. - return 10000; + return 1000; } - return 1000; + return 100; } public function isCommentTransaction() { diff --git a/src/infrastructure/daemon/control/PhabricatorDaemonReference.php b/src/infrastructure/daemon/control/PhabricatorDaemonReference.php index d9f8180935..6c90e1eed4 100644 --- a/src/infrastructure/daemon/control/PhabricatorDaemonReference.php +++ b/src/infrastructure/daemon/control/PhabricatorDaemonReference.php @@ -1,128 +1,10 @@ setViewer(PhabricatorUser::getOmnipotentUser()) - ->withDaemonIDs($daemon_ids) - ->execute(); - } catch (AphrontQueryException $ex) { - // Ignore any issues here; getting this information only allows us - // to provide a more complete picture of daemon status, and we want - // these commands to work if the database is inaccessible. - } - - $logs = mpull($logs, null, 'getDaemonID'); - } - - // Support PID files that use the old daemon format, where each overseer - // had exactly one daemon. We can eventually remove this; they will still - // be stopped by `phd stop --force` even if we don't identify them here. - if (!$daemons && idx($dict, 'name')) { - $daemons = array( - array( - 'config' => array( - 'class' => idx($dict, 'name'), - 'argv' => idx($dict, 'argv', array()), - ), - ), - ); - } - - foreach ($daemons as $daemon) { - $ref = new PhabricatorDaemonReference(); - - // NOTE: This is the overseer PID, not the actual daemon process PID. - // This is correct for checking status and sending signals (the only - // things we do with it), but might be confusing. $daemon['pid'] has - // the daemon PID, and we could expose that if we had some use for it. - - $ref->pid = idx($dict, 'pid'); - $ref->start = idx($dict, 'start'); - - $config = idx($daemon, 'config', array()); - $ref->name = idx($config, 'class'); - $ref->argv = idx($config, 'argv', array()); - - $log = idx($logs, idx($daemon, 'id')); - if ($log) { - $ref->daemonLog = $log; - } - - $ref->pidFile = $path; - $refs[] = $ref; - } - - return $refs; - } - - public function updateStatus($new_status) { - if (!$this->daemonLog) { - return; - } - - try { - $this->daemonLog - ->setStatus($new_status) - ->save(); - } catch (AphrontQueryException $ex) { - // Ignore anything that goes wrong here. - } - } - - public function getPID() { - return $this->pid; - } - - public function getName() { - return $this->name; - } - - public function getArgv() { - return $this->argv; - } - - public function getEpochStarted() { - return $this->start; - } - - public function getPIDFile() { - return $this->pidFile; - } - - public function getDaemonLog() { - return $this->daemonLog; - } - - public function isRunning() { - return self::isProcessRunning($this->getPID()); - } - public static function isProcessRunning($pid) { if (!$pid) { return false; @@ -148,15 +30,4 @@ final class PhabricatorDaemonReference extends Phobject { return $is_running; } - public function waitForExit($seconds) { - $start = time(); - while (time() < $start + $seconds) { - usleep(100000); - if (!$this->isRunning()) { - return true; - } - } - return !$this->isRunning(); - } - } diff --git a/webroot/rsrc/externals/javelin/lib/Workflow.js b/webroot/rsrc/externals/javelin/lib/Workflow.js index d398d33774..3e1bba4a6a 100644 --- a/webroot/rsrc/externals/javelin/lib/Workflow.js +++ b/webroot/rsrc/externals/javelin/lib/Workflow.js @@ -104,7 +104,11 @@ JX.install('Workflow', { var link = event.getNode('tag:a'); // If the link is an anchor, or does not go anywhere, ignore the event. - var href = '' + link.getAttribute('href'); + var href = link.getAttribute('href'); + if (typeof href !== 'string') { + return; + } + if (!href.length || href[0] === '#') { return; }