diff --git a/src/daemon/PhutilDaemonHandle.php b/src/daemon/PhutilDaemonHandle.php --- a/src/daemon/PhutilDaemonHandle.php +++ b/src/daemon/PhutilDaemonHandle.php @@ -341,6 +341,34 @@ } } + public function didReceiveReloadSignal($signo) { + $signame = phutil_get_signal_name($signo); + if ($signame) { + $sigmsg = pht( + 'Reloading in response to signal %d (%s).', + $signo, + $signame); + } else { + $sigmsg = pht( + 'Reloading in response to signal %d.', + $signo); + } + + $this->logMessage('RELO', $sigmsg, $signo); + + // This signal means "stop the current process gracefully, then launch + // a new identical process once it exits". This can be used to update + // daemons after code changes (the new processes will run the new code) + // without aborting any running tasks. + + // We SIGINT the daemon but don't set the shutdown flag, so it will + // naturally be restarted after it exits, as though it had exited after an + // unhandled exception. + + $pid = $this->pid; + exec("kill -INT {$pid}"); + } + public function didReceiveGracefulSignal($signo) { $this->shouldShutdown = true; if (!$this->isRunning()) { diff --git a/src/daemon/PhutilDaemonOverseer.php b/src/daemon/PhutilDaemonOverseer.php --- a/src/daemon/PhutilDaemonOverseer.php +++ b/src/daemon/PhutilDaemonOverseer.php @@ -145,6 +145,7 @@ declare(ticks = 1); pcntl_signal(SIGUSR2, array($this, 'didReceiveNotifySignal')); + pcntl_signal(SIGHUP, array($this, 'didReceiveReloadSignal')); pcntl_signal(SIGINT, array($this, 'didReceiveGracefulSignal')); pcntl_signal(SIGTERM, array($this, 'didReceiveTerminalSignal')); } @@ -346,6 +347,12 @@ } } + public function didReceiveReloadSignal($signo) { + foreach ($this->getDaemonHandles() as $daemon) { + $daemon->didReceiveReloadSignal($signo); + } + } + public function didReceiveGracefulSignal($signo) { // If we receive SIGINT more than once, interpret it like SIGTERM. if ($this->inGracefulShutdown) {