Page MenuHomePhabricator

D10228.id24617.diff
No OneTemporary

D10228.id24617.diff

diff --git a/src/applications/daemon/controller/PhabricatorDaemonLogViewController.php b/src/applications/daemon/controller/PhabricatorDaemonLogViewController.php
--- a/src/applications/daemon/controller/PhabricatorDaemonLogViewController.php
+++ b/src/applications/daemon/controller/PhabricatorDaemonLogViewController.php
@@ -53,6 +53,10 @@
$tag->setBackgroundColor(PHUITagView::COLOR_BLUE);
$tag->setName(pht('Waiting'));
break;
+ case PhabricatorDaemonLog::STATUS_EXITING:
+ $tag->setBackgroundColor(PHUITagView::COLOR_YELLOW);
+ $tag->setName(pht('Exiting'));
+ break;
case PhabricatorDaemonLog::STATUS_EXITED:
$tag->setBackgroundColor(PHUITagView::COLOR_GREY);
$tag->setName(pht('Exited'));
@@ -136,6 +140,10 @@
phutil_format_relative_time($unknown_time),
phutil_format_relative_time($wait_time));
break;
+ case PhabricatorDaemonLog::STATUS_EXITING:
+ $details = pht(
+ 'This daemon is shutting down gracefully.');
+ break;
case PhabricatorDaemonLog::STATUS_EXITED:
$details = pht(
'This daemon exited normally and is no longer running.');
diff --git a/src/applications/daemon/event/PhabricatorDaemonEventListener.php b/src/applications/daemon/event/PhabricatorDaemonEventListener.php
--- a/src/applications/daemon/event/PhabricatorDaemonEventListener.php
+++ b/src/applications/daemon/event/PhabricatorDaemonEventListener.php
@@ -8,6 +8,7 @@
$this->listen(PhutilDaemonOverseer::EVENT_DID_LAUNCH);
$this->listen(PhutilDaemonOverseer::EVENT_DID_LOG);
$this->listen(PhutilDaemonOverseer::EVENT_DID_HEARTBEAT);
+ $this->listen(PhutilDaemonOverseer::EVENT_WILL_GRACEFUL);
$this->listen(PhutilDaemonOverseer::EVENT_WILL_EXIT);
}
@@ -22,6 +23,9 @@
case PhutilDaemonOverseer::EVENT_DID_LOG:
$this->handleLogEvent($event);
break;
+ case PhutilDaemonOverseer::EVENT_WILL_GRACEFUL:
+ $this->handleGracefulEvent($event);
+ break;
case PhutilDaemonOverseer::EVENT_WILL_EXIT:
$this->handleExitEvent($event);
break;
@@ -86,6 +90,13 @@
}
}
+ private function handleGracefulEvent(PhutilEvent $event) {
+ $id = $event->getValue('id');
+
+ $daemon = $this->getDaemon($id);
+ $daemon->setStatus(PhabricatorDaemonLog::STATUS_EXITING)->save();
+ }
+
private function handleExitEvent(PhutilEvent $event) {
$id = $event->getValue('id');
diff --git a/src/applications/daemon/management/PhabricatorDaemonManagementRestartWorkflow.php b/src/applications/daemon/management/PhabricatorDaemonManagementRestartWorkflow.php
--- a/src/applications/daemon/management/PhabricatorDaemonManagementRestartWorkflow.php
+++ b/src/applications/daemon/management/PhabricatorDaemonManagementRestartWorkflow.php
@@ -9,11 +9,22 @@
->setSynopsis(
pht(
'Stop, then start the standard daemon loadout.'))
- ->setArguments(array());
+ ->setArguments(
+ array(
+ array(
+ 'name' => 'graceful',
+ 'param' => 'seconds',
+ 'help' => pht(
+ 'Grace period for daemons to attempt a clean shutdown, in '.
+ 'seconds. Defaults to __15__ seconds.'),
+ 'default' => 15,
+ ),
+ ));
}
public function execute(PhutilArgumentParser $args) {
- $err = $this->executeStopCommand(array());
+ $graceful = $args->getArg('graceful');
+ $err = $this->executeStopCommand(array(), $graceful);
if ($err) {
return $err;
}
diff --git a/src/applications/daemon/management/PhabricatorDaemonManagementStopWorkflow.php b/src/applications/daemon/management/PhabricatorDaemonManagementStopWorkflow.php
--- a/src/applications/daemon/management/PhabricatorDaemonManagementStopWorkflow.php
+++ b/src/applications/daemon/management/PhabricatorDaemonManagementStopWorkflow.php
@@ -13,6 +13,14 @@
->setArguments(
array(
array(
+ 'name' => 'graceful',
+ 'param' => 'seconds',
+ 'help' => pht(
+ 'Grace period for daemons to attempt a clean shutdown, in '.
+ 'seconds. Defaults to __15__ seconds.'),
+ 'default' => 15,
+ ),
+ array(
'name' => 'pids',
'wildcard' => true,
),
@@ -21,7 +29,8 @@
public function execute(PhutilArgumentParser $args) {
$pids = $args->getArg('pids');
- return $this->executeStopCommand($pids);
+ $graceful = $args->getArg('graceful');
+ return $this->executeStopCommand($pids, $graceful);
}
}
diff --git a/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php b/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php
--- a/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php
+++ b/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php
@@ -286,7 +286,7 @@
return 0;
}
- protected final function executeStopCommand(array $pids) {
+ protected final function executeStopCommand(array $pids, $grace_period) {
$console = PhutilConsole::getConsole();
$daemons = $this->loadRunningDaemons();
@@ -325,39 +325,20 @@
}
$all_daemons = $running;
- foreach ($running as $key => $daemon) {
- $pid = $daemon->getPID();
- $name = $daemon->getName();
- $console->writeErr(pht("Stopping daemon '%s' (%s)...", $name, $pid)."\n");
- if (!$daemon->isRunning()) {
- $console->writeErr(pht('Daemon is not running.')."\n");
- unset($running[$key]);
- $daemon->updateStatus(PhabricatorDaemonLog::STATUS_EXITED);
- } else {
- posix_kill($pid, SIGINT);
- }
+ // If we're doing a graceful shutdown, try SIGINT first.
+ if ($grace_period) {
+ $running = $this->sendSignal($running, SIGINT, $grace_period);
}
- $start = time();
- do {
- foreach ($running as $key => $daemon) {
- $pid = $daemon->getPID();
- if (!$daemon->isRunning()) {
- $console->writeOut(pht('Daemon %s exited normally.', $pid)."\n");
- unset($running[$key]);
- }
- }
- if (empty($running)) {
- break;
- }
- usleep(100000);
- } while (time() < $start + 15);
+ // If we still have daemons, SIGTERM them.
+ if ($running) {
+ $running = $this->sendSignal($running, SIGTERM, 15);
+ }
- foreach ($running as $key => $daemon) {
- $pid = $daemon->getPID();
- $console->writeErr(pht('Sending daemon %s a SIGKILL.', $pid)."\n");
- posix_kill($pid, SIGKILL);
+ // If the overseer is still alive, SIGKILL it.
+ if ($running) {
+ $this->sendSignal($running, SIGKILL, 0);
}
foreach ($all_daemons as $daemon) {
@@ -369,6 +350,49 @@
return 0;
}
+ private function sendSignal(array $daemons, $signo, $wait) {
+ $console = PhutilConsole::getConsole();
+
+ foreach ($daemons as $key => $daemon) {
+ $pid = $daemon->getPID();
+ $name = $daemon->getName();
+
+ switch ($signo) {
+ case SIGINT:
+ $message = pht("Interrupting daemon '%s' (%s)...", $name, $pid);
+ break;
+ case SIGTERM:
+ $message = pht("Terminating daemon '%s' (%s)...", $name, $pid);
+ break;
+ case SIGKILL:
+ $message = pht("Killing daemon '%s' (%s)...", $name, $pid);
+ break;
+ }
+
+ $console->writeOut("%s\n", $message);
+ posix_kill($pid, $signo);
+ }
+
+ if ($wait) {
+ $start = PhabricatorTime::getNow();
+ do {
+ foreach ($daemons as $key => $daemon) {
+ $pid = $daemon->getPID();
+ if (!$daemon->isRunning()) {
+ $console->writeOut(pht('Daemon %s exited.', $pid)."\n");
+ unset($daemons[$key]);
+ }
+ }
+ if (empty($daemons)) {
+ break;
+ }
+ usleep(100000);
+ } while (PhabricatorTime::getNow() < $start + $wait);
+ }
+
+ return $daemons;
+ }
+
private function freeActiveLeases() {
$task_table = id(new PhabricatorWorkerActiveTask());
$conn_w = $task_table->establishConnection('w');
diff --git a/src/applications/daemon/query/PhabricatorDaemonLogQuery.php b/src/applications/daemon/query/PhabricatorDaemonLogQuery.php
--- a/src/applications/daemon/query/PhabricatorDaemonLogQuery.php
+++ b/src/applications/daemon/query/PhabricatorDaemonLogQuery.php
@@ -67,6 +67,7 @@
$status_running = PhabricatorDaemonLog::STATUS_RUNNING;
$status_unknown = PhabricatorDaemonLog::STATUS_UNKNOWN;
$status_wait = PhabricatorDaemonLog::STATUS_WAIT;
+ $status_exiting = PhabricatorDaemonLog::STATUS_EXITING;
$status_exited = PhabricatorDaemonLog::STATUS_EXITED;
$status_dead = PhabricatorDaemonLog::STATUS_DEAD;
@@ -77,7 +78,8 @@
$seen = $daemon->getDateModified();
$is_running = ($status == $status_running) ||
- ($status == $status_wait);
+ ($status == $status_wait) ||
+ ($status == $status_exiting);
// If we haven't seen the daemon recently, downgrade its status to
// unknown.
@@ -160,6 +162,7 @@
PhabricatorDaemonLog::STATUS_UNKNOWN,
PhabricatorDaemonLog::STATUS_RUNNING,
PhabricatorDaemonLog::STATUS_WAIT,
+ PhabricatorDaemonLog::STATUS_EXITING,
);
default:
throw new Exception("Unknown status '{$status}'!");
diff --git a/src/applications/daemon/storage/PhabricatorDaemonLog.php b/src/applications/daemon/storage/PhabricatorDaemonLog.php
--- a/src/applications/daemon/storage/PhabricatorDaemonLog.php
+++ b/src/applications/daemon/storage/PhabricatorDaemonLog.php
@@ -7,6 +7,7 @@
const STATUS_RUNNING = 'run';
const STATUS_DEAD = 'dead';
const STATUS_WAIT = 'wait';
+ const STATUS_EXITING = 'exiting';
const STATUS_EXITED = 'exit';
protected $daemon;
diff --git a/src/applications/daemon/view/PhabricatorDaemonLogListView.php b/src/applications/daemon/view/PhabricatorDaemonLogListView.php
--- a/src/applications/daemon/view/PhabricatorDaemonLogListView.php
+++ b/src/applications/daemon/view/PhabricatorDaemonLogListView.php
@@ -17,8 +17,7 @@
throw new Exception('Call setUser() before rendering!');
}
- $list = id(new PHUIObjectItemListView())
- ->setFlush(true);
+ $list = new PHUIObjectItemListView();
foreach ($this->daemonLogs as $log) {
$id = $log->getID();
$epoch = $log->getDateCreated();
@@ -43,6 +42,10 @@
'dead.'));
$item->addIcon('fa-times grey', pht('Dead'));
break;
+ case PhabricatorDaemonLog::STATUS_EXITING:
+ $item->addAttribute(pht('This daemon is exiting.'));
+ $item->addIcon('fa-check', pht('Exiting'));
+ break;
case PhabricatorDaemonLog::STATUS_EXITED:
$item->setDisabled(true);
$item->addAttribute(pht('This daemon exited cleanly.'));
diff --git a/src/applications/fact/daemon/PhabricatorFactDaemon.php b/src/applications/fact/daemon/PhabricatorFactDaemon.php
--- a/src/applications/fact/daemon/PhabricatorFactDaemon.php
+++ b/src/applications/fact/daemon/PhabricatorFactDaemon.php
@@ -8,7 +8,7 @@
public function run() {
$this->setEngines(PhabricatorFactEngine::loadAllEngines());
- while (true) {
+ while (!$this->shouldExit()) {
$iterators = $this->getAllApplicationIterators();
foreach ($iterators as $iterator_name => $iterator) {
$this->processIteratorWithCursor($iterator_name, $iterator);
diff --git a/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php b/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php
--- a/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php
+++ b/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php
@@ -71,7 +71,7 @@
$futures = array();
$queue = array();
- while (true) {
+ while (!$this->shouldExit()) {
$pullable = $this->loadPullableRepositories($include, $exclude);
// If any repositories have the NEEDS_UPDATE flag set, pull them
@@ -422,6 +422,12 @@
new PhutilNumber($sleep_duration)));
$this->sleep(1);
+
+ if ($this->shouldExit()) {
+ $this->log(pht('Awakened from sleep by graceful shutdown!'));
+ return;
+ }
+
if ($this->loadRepositoryUpdateMessages()) {
$this->log(pht('Awakened from sleep by pending updates!'));
break;
diff --git a/src/infrastructure/daemon/bot/PhabricatorBot.php b/src/infrastructure/daemon/bot/PhabricatorBot.php
--- a/src/infrastructure/daemon/bot/PhabricatorBot.php
+++ b/src/infrastructure/daemon/bot/PhabricatorBot.php
@@ -103,7 +103,7 @@
foreach ($this->handlers as $handler) {
$handler->runBackgroundTasks();
}
- } while (true);
+ } while (!$this->shouldExit());
}
public function writeMessage(PhabricatorBotMessage $message) {
diff --git a/src/infrastructure/daemon/garbagecollector/PhabricatorGarbageCollectorDaemon.php b/src/infrastructure/daemon/garbagecollector/PhabricatorGarbageCollectorDaemon.php
--- a/src/infrastructure/daemon/garbagecollector/PhabricatorGarbageCollectorDaemon.php
+++ b/src/infrastructure/daemon/garbagecollector/PhabricatorGarbageCollectorDaemon.php
@@ -31,7 +31,7 @@
// scans just to delete a handful of rows; wake up in a few hours.
$this->log(pht('All caught up, waiting for more garbage.'));
$this->sleep(4 * (60 * 60));
- } while (true);
+ } while (!$this->shouldExit());
}
diff --git a/src/infrastructure/daemon/workers/PhabricatorTaskmasterDaemon.php b/src/infrastructure/daemon/workers/PhabricatorTaskmasterDaemon.php
--- a/src/infrastructure/daemon/workers/PhabricatorTaskmasterDaemon.php
+++ b/src/infrastructure/daemon/workers/PhabricatorTaskmasterDaemon.php
@@ -40,7 +40,7 @@
}
$this->sleep($sleep);
- } while (true);
+ } while (!$this->shouldExit());
}
}

File Metadata

Mime Type
text/plain
Expires
Thu, Nov 7, 10:01 PM (5 d, 6 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6724100
Default Alt Text
D10228.id24617.diff (13 KB)

Event Timeline