mirror of
https://we.phorge.it/source/phorge.git
synced 2025-02-22 19:49:02 +01: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:
parent
75c3598359
commit
d98bf8ef8e
3 changed files with 72 additions and 102 deletions
|
@ -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'),
|
||||
|
|
|
@ -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'),
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue