diff --git a/PHPDaemon/Core/Bootstrap.php b/PHPDaemon/Core/Bootstrap.php index a91e3b37..1834aa1d 100644 --- a/PHPDaemon/Core/Bootstrap.php +++ b/PHPDaemon/Core/Bootstrap.php @@ -30,7 +30,7 @@ class Bootstrap { * @var array */ protected static $commands = [ - 'start', 'stop', 'hardstop', 'update', 'reload', 'restart', 'hardrestart', 'fullstatus', 'status', 'configtest', 'log', 'runworker' + 'start', 'stop', 'hardstop', 'gracefulstop', 'update', 'reload', 'restart', 'hardrestart', 'fullstatus', 'status', 'configtest', 'log', 'runworker' ]; /** @@ -427,6 +427,9 @@ public static function init($configFile = null) { elseif ($runmode == 'stop') { Bootstrap::stop(); } + elseif ($runmode == 'gracefulstop') { + Bootstrap::stop(4); + } elseif ($runmode == 'hardstop') { echo '[HARDSTOP] Sending SIGINT to ' . Bootstrap::$pid . '... '; @@ -468,7 +471,7 @@ public static function init($configFile = null) { * @return void */ protected static function printUsage() { - echo 'usage: ' . Daemon::$runName . " (start|(hard)stop|update|reload|(hard)restart|fullstatus|status|configtest|log|runworker|help) ...\n"; + echo 'usage: ' . Daemon::$runName . " (start|(hard|graceful)stop|update|reload|(hard)restart|fullstatus|status|configtest|log|runworker|help) ...\n"; } /** @@ -537,7 +540,7 @@ public static function runworker() { * @return void */ public static function stop($mode = 1) { - $ok = Bootstrap::$pid && posix_kill(Bootstrap::$pid, $mode === 3 ? SIGINT : SIGTERM); + $ok = Bootstrap::$pid && posix_kill(Bootstrap::$pid, $mode === 3 ? SIGINT : (($mode === 4) ? SIGTSTP : SIGTERM)); if (!$ok) { echo '[WARN]. It seems that phpDaemon is not running' . (Bootstrap::$pid ? ' (PID ' . Bootstrap::$pid . ')' : '') . ".\n"; diff --git a/PHPDaemon/Thread/Generic.php b/PHPDaemon/Thread/Generic.php index dce60854..d1cd3230 100644 --- a/PHPDaemon/Thread/Generic.php +++ b/PHPDaemon/Thread/Generic.php @@ -75,6 +75,7 @@ abstract class Generic { SIGWINCH => 'SIGWINCH', SIGUSR1 => 'SIGUSR1', SIGUSR2 => 'SIGUSR2', + SIGTSTP => 'SIGTSTP', ]; /** diff --git a/PHPDaemon/Thread/IPC.php b/PHPDaemon/Thread/IPC.php index 8519984a..3d73d320 100644 --- a/PHPDaemon/Thread/IPC.php +++ b/PHPDaemon/Thread/IPC.php @@ -281,6 +281,18 @@ public function sigquit() { parent::sigquit(); } + /** + * Handler of the SIGTSTP (graceful stop) signal in worker process. + * @return void + */ + protected function sigtstp() { + if (Daemon::$config->logsignals->value) { + $this->log('Caught SIGTSTP (graceful stop all workers).'); + } + + $this->shutdown(); + } + /** * Handler of the SIGHUP (reload config) signal in worker process. * @return void diff --git a/PHPDaemon/Thread/Master.php b/PHPDaemon/Thread/Master.php index 5b54295b..9470bf60 100644 --- a/PHPDaemon/Thread/Master.php +++ b/PHPDaemon/Thread/Master.php @@ -397,6 +397,19 @@ protected function sigquit() { $this->shutdown(SIGQUIT); } + /** + * Handler for the SIGTSTP (graceful stop all workers) signal in master process + * @return void + */ + protected function sigtstp() { + if (Daemon::$config->logsignals->value) { + $this->log('Caught SIGTSTP (graceful stop all workers).'); + } + + $this->signalToChildren(SIGTSTP); + $this->shutdown(SIGTSTP); + } + /** * Handler for the SIGHUP (reload config) signal in master process * @return void diff --git a/PHPDaemon/Thread/Worker.php b/PHPDaemon/Thread/Worker.php index a45ea6c5..8ecc5efe 100644 --- a/PHPDaemon/Thread/Worker.php +++ b/PHPDaemon/Thread/Worker.php @@ -533,6 +533,17 @@ public function gracefulRestart() { $this->setState($this->state); } + /** + * Graceful stop + * @return void + */ + public function gracefulStop() { + $this->breakMainLoop = true; + $this->graceful = true; + $this->reloadTime = microtime(true) + $this->reloadDelay; + $this->setState($this->state); + } + /** * Asks the running applications the whether we can go to shutdown current (old) worker. * @return boolean - Ready? @@ -727,6 +738,18 @@ protected function sigusr2() { $this->gracefulRestart(); } + /** + * Handler of the SIGTSTP (graceful stop) signal in worker process. + * @return void + */ + protected function sigtstp() { + if (Daemon::$config->logsignals->value) { + $this->log('caught SIGTSTP (graceful stop).'); + } + + $this->gracefulStop(); + } + /** * Handler of the SIGTTIN signal in worker process. * @return void