1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-02-24 20:49:06 +01:00

(stable) Promote 2020 Week 29

This commit is contained in:
epriestley 2020-07-25 08:25:06 -07:00
commit 1b54f45c4c
10 changed files with 158 additions and 104 deletions

View file

@ -8,14 +8,21 @@ final class PhabricatorDaemonsSetupCheck extends PhabricatorSetupCheck {
protected function executeChecks() { protected function executeChecks() {
$task_daemon = id(new PhabricatorDaemonLogQuery()) try {
$task_daemons = id(new PhabricatorDaemonLogQuery())
->setViewer(PhabricatorUser::getOmnipotentUser()) ->setViewer(PhabricatorUser::getOmnipotentUser())
->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE) ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE)
->withDaemonClasses(array('PhabricatorTaskmasterDaemon')) ->withDaemonClasses(array('PhabricatorTaskmasterDaemon'))
->setLimit(1) ->setLimit(1)
->execute(); ->execute();
if (!$task_daemon) { $no_daemons = !$task_daemons;
} catch (Exception $ex) {
// Just skip this warning if the query fails for some reason.
$no_daemons = false;
}
if ($no_daemons) {
$doc_href = PhabricatorEnv::getDoclink('Managing Daemons with phd'); $doc_href = PhabricatorEnv::getDoclink('Managing Daemons with phd');
$summary = pht( $summary = pht(

View file

@ -322,6 +322,9 @@ final class PhabricatorExtraConfigSetupCheck extends PhabricatorSetupCheck {
'directly supported. Prefixes and other strings may be customized with '. 'directly supported. Prefixes and other strings may be customized with '.
'"translation.override".'); '"translation.override".');
$phd_reason = pht(
'Use "bin/phd debug ..." to get a detailed daemon execution log.');
$ancient_config += array( $ancient_config += array(
'phid.external-loaders' => 'phid.external-loaders' =>
pht( pht(
@ -539,6 +542,9 @@ final class PhabricatorExtraConfigSetupCheck extends PhabricatorSetupCheck {
'phd.pid-directory' => pht( 'phd.pid-directory' => pht(
'Phabricator daemons no longer use PID files.'), 'Phabricator daemons no longer use PID files.'),
'phd.trace' => $phd_reason,
'phd.verbose' => $phd_reason,
); );
return $ancient_config; return $ancient_config;

View file

@ -43,22 +43,6 @@ final class PhabricatorPHDConfigOptions
"configuration changes are picked up by the daemons ". "configuration changes are picked up by the daemons ".
"automatically, but pool sizes can not be changed without a ". "automatically, but pool sizes can not be changed without a ".
"restart.")), "restart.")),
$this->newOption('phd.verbose', 'bool', false)
->setLocked(true)
->setBoolOptions(
array(
pht('Verbose mode'),
pht('Normal mode'),
))
->setSummary(pht("Launch daemons in 'verbose' mode by default."))
->setDescription(
pht(
"Launch daemons in 'verbose' mode by default. This creates a lot ".
"of output, but can help debug issues. Daemons launched in debug ".
"mode with '%s' are always launched in verbose mode. ".
"See also '%s'.",
'phd debug',
'phd.trace')),
$this->newOption('phd.user', 'string', null) $this->newOption('phd.user', 'string', null)
->setLocked(true) ->setLocked(true)
->setSummary(pht('System user to run daemons as.')) ->setSummary(pht('System user to run daemons as.'))
@ -68,22 +52,6 @@ final class PhabricatorPHDConfigOptions
'user will own the working copies of any repositories that '. 'user will own the working copies of any repositories that '.
'Phabricator imports or manages. This option is new and '. 'Phabricator imports or manages. This option is new and '.
'experimental.')), 'experimental.')),
$this->newOption('phd.trace', 'bool', false)
->setLocked(true)
->setBoolOptions(
array(
pht('Trace mode'),
pht('Normal mode'),
))
->setSummary(pht("Launch daemons in 'trace' mode by default."))
->setDescription(
pht(
"Launch daemons in 'trace' mode by default. This creates an ".
"ENORMOUS amount of output, but can help debug issues. Daemons ".
"launched in debug mode with '%s' are always launched in ".
"trace mode. See also '%s'.",
'phd debug',
'phd.verbose')),
$this->newOption('phd.garbage-collection', 'wild', array()) $this->newOption('phd.garbage-collection', 'wild', array())
->setLocked(true) ->setLocked(true)
->setLockedMessage( ->setLockedMessage(

View file

@ -116,11 +116,11 @@ abstract class PhabricatorDaemonManagementWorkflow
$trace = PhutilArgumentParser::isTraceModeEnabled(); $trace = PhutilArgumentParser::isTraceModeEnabled();
$flags = array(); $flags = array();
if ($trace || PhabricatorEnv::getEnvConfig('phd.trace')) { if ($trace) {
$flags[] = '--trace'; $flags[] = '--trace';
} }
if ($debug || PhabricatorEnv::getEnvConfig('phd.verbose')) { if ($debug) {
$flags[] = '--verbose'; $flags[] = '--verbose';
} }

View file

@ -16,7 +16,6 @@ final class PhutilDaemonHandle extends Phobject {
private $restartAt; private $restartAt;
private $busyEpoch; private $busyEpoch;
private $pid;
private $daemonID; private $daemonID;
private $deadline; private $deadline;
private $heartbeat; private $heartbeat;
@ -104,7 +103,7 @@ final class PhutilDaemonHandle extends Phobject {
} }
public function isRunning() { public function isRunning() {
return (bool)$this->future; return (bool)$this->getFuture();
} }
public function isHibernating() { public function isHibernating() {
@ -134,10 +133,6 @@ final class PhutilDaemonHandle extends Phobject {
return (!$this->shouldRestart && !$this->isRunning()); return (!$this->shouldRestart && !$this->isRunning());
} }
public function getFuture() {
return $this->future;
}
public function update() { public function update() {
if (!$this->isRunning()) { if (!$this->isRunning()) {
if (!$this->shouldRestart) { if (!$this->shouldRestart) {
@ -152,11 +147,19 @@ final class PhutilDaemonHandle extends Phobject {
$this->startDaemonProcess(); $this->startDaemonProcess();
} }
$future = $this->future; $future = $this->getFuture();
$result = null; $result = null;
if ($future->isReady()) { $caught = null;
if ($future->canResolve()) {
$this->future = null;
try {
$result = $future->resolve(); $result = $future->resolve();
} catch (Exception $ex) {
$caught = $ex;
} catch (Throwable $ex) {
$caught = $ex;
}
} }
list($stdout, $stderr) = $future->read(); list($stdout, $stderr) = $future->read();
@ -173,7 +176,14 @@ final class PhutilDaemonHandle extends Phobject {
} }
} }
if ($result !== null) { if ($result !== null || $caught !== null) {
if ($caught) {
$message = pht(
'Process failed with exception: %s',
$caught->getMessage());
$this->logMessage('FAIL', $message);
} else {
list($err) = $result; list($err) = $result;
if ($err) { if ($err) {
@ -181,8 +191,7 @@ final class PhutilDaemonHandle extends Phobject {
} else { } else {
$this->logMessage('DONE', pht('Process exited normally.')); $this->logMessage('DONE', pht('Process exited normally.'));
} }
}
$this->future = null;
if ($this->shouldShutdown) { if ($this->shouldShutdown) {
$this->restartAt = null; $this->restartAt = null;
@ -244,8 +253,22 @@ final class PhutilDaemonHandle extends Phobject {
return $this->daemonID; return $this->daemonID;
} }
public function getPID() { private function getFuture() {
return $this->pid; return $this->future;
}
private function getPID() {
$future = $this->getFuture();
if (!$future) {
return null;
}
if (!$future->hasPID()) {
return null;
}
return $future->getPID();
} }
private function getCaptureBufferSize() { private function getCaptureBufferSize() {
@ -327,15 +350,16 @@ final class PhutilDaemonHandle extends Phobject {
private function annihilateProcessGroup() { private function annihilateProcessGroup() {
$pid = $this->getPID(); $pid = $this->getPID();
if ($pid) {
$pgid = posix_getpgid($pid); $pgid = posix_getpgid($pid);
if ($pid && $pgid) { if ($pgid) {
posix_kill(-$pgid, SIGTERM); posix_kill(-$pgid, SIGTERM);
sleep($this->getKillDelay()); sleep($this->getKillDelay());
posix_kill(-$pgid, SIGKILL); posix_kill(-$pgid, SIGKILL);
$this->pid = null; $this->pid = null;
} }
} }
}
private function startDaemonProcess() { private function startDaemonProcess() {
$this->logMessage('INIT', pht('Starting process.')); $this->logMessage('INIT', pht('Starting process.'));
@ -345,10 +369,12 @@ final class PhutilDaemonHandle extends Phobject {
$this->stdoutBuffer = ''; $this->stdoutBuffer = '';
$this->hibernating = false; $this->hibernating = false;
$this->future = $this->newExecFuture(); $future = $this->newExecFuture();
$this->future->start(); $this->future = $future;
$this->pid = $this->future->getPID(); $pool = $this->getDaemonPool();
$overseer = $pool->getOverseer();
$overseer->addFutureToPool($future);
} }
private function didReadStdout($data) { private function didReadStdout($data) {
@ -440,7 +466,10 @@ final class PhutilDaemonHandle extends Phobject {
// naturally be restarted after it exits, as though it had exited after an // naturally be restarted after it exits, as though it had exited after an
// unhandled exception. // unhandled exception.
posix_kill($this->getPID(), SIGINT); $pid = $this->getPID();
if ($pid) {
posix_kill($pid, SIGINT);
}
} }
public function didReceiveGracefulSignal($signo) { public function didReceiveGracefulSignal($signo) {
@ -461,7 +490,10 @@ final class PhutilDaemonHandle extends Phobject {
$this->logMessage('DONE', $sigmsg, $signo); $this->logMessage('DONE', $sigmsg, $signo);
posix_kill($this->getPID(), SIGINT); $pid = $this->getPID();
if ($pid) {
posix_kill($pid, SIGINT);
}
} }
public function didReceiveTerminateSignal($signo) { public function didReceiveTerminateSignal($signo) {

View file

@ -181,10 +181,6 @@ EOHELP
} }
} }
foreach ($pool->getFutures() as $future) {
$future_pool->addFuture($future);
}
if ($pool->getDaemons()) { if ($pool->getDaemons()) {
$running_pools = true; $running_pools = true;
} }
@ -210,6 +206,11 @@ EOHELP
exit($this->err); exit($this->err);
} }
public function addFutureToPool(Future $future) {
$this->getFuturePool()->addFuture($future);
return $this;
}
private function getFuturePool() { private function getFuturePool() {
if (!$this->futurePool) { if (!$this->futurePool) {
$pool = new FuturePool(); $pool = new FuturePool();

View file

@ -111,18 +111,6 @@ final class PhutilDaemonPool extends Phobject {
return $this->daemons; return $this->daemons;
} }
public function getFutures() {
$futures = array();
foreach ($this->getDaemons() as $daemon) {
$future = $daemon->getFuture();
if ($future) {
$futures[] = $future;
}
}
return $futures;
}
public function didReceiveSignal($signal, $signo) { public function didReceiveSignal($signal, $signo) {
switch ($signal) { switch ($signal) {
case PhutilDaemonOverseer::SIGNAL_GRACEFUL: case PhutilDaemonOverseer::SIGNAL_GRACEFUL:

View file

@ -24,7 +24,7 @@ final class PhabricatorTaskmasterDaemon extends PhabricatorDaemon {
if ($ex) { if ($ex) {
if ($ex instanceof PhabricatorWorkerPermanentFailureException) { if ($ex instanceof PhabricatorWorkerPermanentFailureException) {
// NOTE: Make sure these reach the daemon log, even when not // NOTE: Make sure these reach the daemon log, even when not
// running in "phd.verbose" mode. See T12803 for discussion. // running in verbose mode. See T12803 for discussion.
$log_exception = new PhutilProxyException( $log_exception = new PhutilProxyException(
pht( pht(
'Task "%s" encountered a permanent failure and was '. 'Task "%s" encountered a permanent failure and was '.

View file

@ -142,22 +142,9 @@ final class PhutilProseDifferenceEngine extends Phobject {
} }
if ($level < 2) { if ($level < 2) {
// Split pieces into separate text and whitespace sections: make one $trimmed_pieces = $this->trimApart($result);
// piece out of all the whitespace at the beginning, one piece out of foreach ($trimmed_pieces as $trimmed_piece) {
// all the actual text in the middle, and one piece out of all the $results[] = $trimmed_piece;
// whitespace at the end.
$matches = null;
preg_match('/^(\s*)(.*?)(\s*)\z/s', $result, $matches);
if (strlen($matches[1])) {
$results[] = $matches[1];
}
if (strlen($matches[2])) {
$results[] = $matches[2];
}
if (strlen($matches[3])) {
$results[] = $matches[3];
} }
} else { } else {
$results[] = $result; $results[] = $result;
@ -272,4 +259,36 @@ final class PhutilProseDifferenceEngine extends Phobject {
return $blocks; return $blocks;
} }
public static function trimApart($input) {
// Split pieces into separate text and whitespace sections: make one
// piece out of all the whitespace at the beginning, one piece out of
// all the actual text in the middle, and one piece out of all the
// whitespace at the end.
$parts = array();
$length = strlen($input);
$corpus = ltrim($input);
$l_length = strlen($corpus);
if ($l_length !== $length) {
$parts[] = substr($input, 0, $length - $l_length);
}
$corpus = rtrim($corpus);
$lr_length = strlen($corpus);
if ($lr_length) {
$parts[] = $corpus;
}
if ($lr_length !== $l_length) {
// NOTE: This will be a negative value; we're slicing from the end of
// the input string.
$parts[] = substr($input, $lr_length - $l_length);
}
return $parts;
}
} }

View file

@ -3,6 +3,39 @@
final class PhutilProseDiffTestCase final class PhutilProseDiffTestCase
extends PhabricatorTestCase { extends PhabricatorTestCase {
public function testTrimApart() {
$map = array(
'' => array(),
'a' => array('a'),
' a ' => array(
' ',
'a',
' ',
),
' a' => array(
' ',
'a',
),
'a ' => array(
'a',
' ',
),
' a b ' => array(
' ',
'a b',
' ',
),
);
foreach ($map as $input => $expect) {
$actual = PhutilProseDifferenceEngine::trimApart($input);
$this->assertEqual(
$expect,
$actual,
pht('Trim Apart: %s', $input));
}
}
public function testProseDiffsDistance() { public function testProseDiffsDistance() {
$this->assertProseParts( $this->assertProseParts(
'', '',