1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-09-20 09:18:48 +02:00

Drive "phd stop" entirely from the process list, not PID files on disk

Summary:
Ref T13321. Depends on D20600. Make `bin/phd stop` mean:

  - `bin/phd stop`: Stop all processes which have daemon process titles. If we're instanced, only stop daemons for the current instance.
  - `bin/phd stop --force`: Stop all processes which have deamon process titles for any instance.

We no longer read or care about PID files on disk, and this moves us away from PID files.

This makes unusual flag `--gently` do nothing. A followup will update the documentation and flags to reflect actual usage/behavior.

This also removes the ability to stop specific PIDs. This was somewhat useful long, long ago when you might explicitly run different copies of the `PullLocal` daemon with flags to control which repositories they updated, but with the advent of clustering it's no longer valid to run custom daemon loadouts.

Test Plan: Ran `bin/phd start`, then `bin/phd stop`. Saw instance daemons stop. Ran `bin/phd stop --force`, saw all daemons stop.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13321

Differential Revision: https://secure.phabricator.com/D20601
This commit is contained in:
epriestley 2019-06-20 13:54:13 -07:00
parent 75c3598359
commit d98bf8ef8e
3 changed files with 72 additions and 102 deletions

View file

@ -35,7 +35,6 @@ final class PhabricatorDaemonManagementRestartWorkflow
public function execute(PhutilArgumentParser $args) {
$err = $this->executeStopCommand(
array(),
array(
'graceful' => $args->getArg('graceful'),
'force' => $args->getArg('force'),

View file

@ -42,7 +42,6 @@ final class PhabricatorDaemonManagementStopWorkflow
public function execute(PhutilArgumentParser $args) {
return $this->executeStopCommand(
$args->getArg('pids'),
array(
'graceful' => $args->getArg('graceful'),
'force' => $args->getArg('force'),

View file

@ -386,78 +386,86 @@ 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 = PhabricatorEnv::getEnvConfig('cluster.instance');
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;
@ -492,42 +500,6 @@ abstract class PhabricatorDaemonManagementWorkflow
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) {