Page MenuHomePhabricator

D10227.diff
No OneTemporary

D10227.diff

diff --git a/src/daemon/PhutilDaemon.php b/src/daemon/PhutilDaemon.php
--- a/src/daemon/PhutilDaemon.php
+++ b/src/daemon/PhutilDaemon.php
@@ -12,6 +12,7 @@
private $traceMemory;
private $verbose;
private $notifyReceived;
+ private $inGracefulShutdown;
final public function setVerbose($verbose) {
$this->verbose = $verbose;
@@ -31,10 +32,10 @@
if (!self::$sighandlerInstalled) {
self::$sighandlerInstalled = true;
- pcntl_signal(SIGINT, __CLASS__.'::exitOnSignal');
pcntl_signal(SIGTERM, __CLASS__.'::exitOnSignal');
}
+ pcntl_signal(SIGINT, array($this, 'onGracefulSignal'));
pcntl_signal(SIGUSR2, array($this, 'onNotifySignal'));
// Without discard mode, this consumes unbounded amounts of memory. Keep
@@ -53,11 +54,17 @@
}
}
+ final public function shouldExit() {
+ return $this->inGracefulShutdown;
+ }
+
final protected function sleep($duration) {
$this->notifyReceived = false;
$this->willSleep($duration);
$this->stillWorking();
- while ($duration > 0 && !$this->notifyReceived) {
+ while ($duration > 0 &&
+ !$this->notifyReceived &&
+ !$this->shouldExit()) {
sleep(min($duration, 60));
$duration -= 60;
$this->stillWorking();
@@ -107,7 +114,11 @@
return $this->traceMode;
}
- public final function onNotifySignal($signo) {
+ final public function onGracefulSignal($signo) {
+ $this->inGracefulShutdown = true;
+ }
+
+ final public function onNotifySignal($signo) {
$this->notifyReceived = true;
$this->onNotify($signo);
}
diff --git a/src/daemon/PhutilDaemonOverseer.php b/src/daemon/PhutilDaemonOverseer.php
--- a/src/daemon/PhutilDaemonOverseer.php
+++ b/src/daemon/PhutilDaemonOverseer.php
@@ -8,6 +8,7 @@
const EVENT_DID_LAUNCH = 'daemon.didLaunch';
const EVENT_DID_LOG = 'daemon.didLogMessage';
const EVENT_DID_HEARTBEAT = 'daemon.didHeartbeat';
+ const EVENT_WILL_GRACEFUL = 'daemon.willGraceful';
const EVENT_WILL_EXIT = 'daemon.willExit';
const HEARTBEAT_WAIT = 120;
@@ -24,7 +25,8 @@
private $argv;
private $moreArgs;
private $childPID;
- private $signaled;
+ private $inAbruptShutdown;
+ private $inGracefulShutdown;
private static $instance;
private $traceMode;
@@ -168,7 +170,7 @@
pcntl_signal(SIGUSR1, array($this, 'didReceiveKeepaliveSignal'));
pcntl_signal(SIGUSR2, array($this, 'didReceiveNotifySignal'));
- pcntl_signal(SIGINT, array($this, 'didReceiveTerminalSignal'));
+ pcntl_signal(SIGINT, array($this, 'didReceiveGracefulSignal'));
pcntl_signal(SIGTERM, array($this, 'didReceiveTerminalSignal'));
}
@@ -269,9 +271,23 @@
$this->annihilateProcessGroup();
} while (false);
+ if ($this->inGracefulShutdown) {
+ // If we just exited because of a graceful shutdown, break now.
+ break;
+ }
+
$this->logMessage('WAIT', 'Waiting to restart process.');
sleep(self::RESTART_WAIT);
+
+ if ($this->inGracefulShutdown) {
+ // If we were awakend by a graceful shutdown, break now.
+ break;
+ }
}
+
+ // This is a clean exit after a graceful shutdown.
+ $this->dispatchEvent(self::EVENT_WILL_EXIT);
+ exit(0);
}
public function didReceiveNotifySignal($signo) {
@@ -285,11 +301,35 @@
$this->deadline = time() + $this->deadlineTimeout;
}
+ public function didReceiveGracefulSignal($signo) {
+ // If we receive SIGINT more than once, interpret it like SIGTERM.
+ if ($this->inGracefulShutdown) {
+ return $this->didReceiveTerminalSignal($signo);
+ }
+ $this->inGracefulShutdown = true;
+
+ $signame = phutil_get_signal_name($signo);
+ if ($signame) {
+ $sigmsg = pht(
+ 'Graceful shutdown in response to signal %d (%s).',
+ $signo,
+ $signame);
+ } else {
+ $sigmsg = pht(
+ 'Graceful shutdown in response to signal %d.',
+ $signo);
+ }
+
+ $this->logMessage('DONE', $sigmsg, $signo);
+
+ $this->gracefulProcessGroup();
+ }
+
public function didReceiveTerminalSignal($signo) {
- if ($this->signaled) {
+ if ($this->inAbruptShutdown) {
exit(128 + $signo);
}
- $this->signaled = true;
+ $this->inAbruptShutdown = true;
$signame = phutil_get_signal_name($signo);
if ($signame) {
@@ -358,6 +398,15 @@
}
+ private function gracefulProcessGroup() {
+ $pid = $this->childPID;
+ $pgid = posix_getpgid($pid);
+ if ($pid && $pgid) {
+ exec("kill -INT -{$pgid}");
+ }
+ }
+
+
/**
* Identify running daemons by examining the process table. This isn't
* completely reliable, but can be used as a fallback if the pid files fail

File Metadata

Mime Type
text/plain
Expires
Sun, Jun 23, 3:40 PM (2 w, 3 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6277236
Default Alt Text
D10227.diff (4 KB)

Event Timeline