Index: src/daemon/PhutilDaemon.php =================================================================== --- src/daemon/PhutilDaemon.php +++ src/daemon/PhutilDaemon.php @@ -12,6 +12,7 @@ private $traceMode; private $traceMemory; private $verbose; + private $notifyReceived; final public function setVerbose($verbose) { $this->verbose = $verbose; @@ -35,6 +36,8 @@ pcntl_signal(SIGTERM, __CLASS__.'::exitOnSignal'); } + pcntl_signal(SIGUSR2, array($this, 'onNotifySignal')); + // Without discard mode, this consumes unbounded amounts of memory. Keep // memory bounded. PhutilServiceProfiler::getInstance()->enableDiscardMode(); @@ -52,9 +55,10 @@ } final protected function sleep($duration) { + $this->notifyReceived = false; $this->willSleep($duration); $this->stillWorking(); - while ($duration > 0) { + while ($duration > 0 && !$this->notifyReceived) { sleep(min($duration, 60)); $duration -= 60; $this->stillWorking(); @@ -104,6 +108,15 @@ return $this->traceMode; } + public final function onNotifySignal($signo) { + $this->notifyReceived = true; + $this->onNotify($signo); + } + + protected function onNotify($signo) { + // This is a hook for subclasses. + } + protected function willRun() { // This is a hook for subclasses. } Index: src/daemon/PhutilDaemonOverseer.php =================================================================== --- src/daemon/PhutilDaemonOverseer.php +++ src/daemon/PhutilDaemonOverseer.php @@ -165,6 +165,7 @@ declare(ticks = 1); pcntl_signal(SIGUSR1, array($this, 'didReceiveKeepaliveSignal')); + pcntl_signal(SIGUSR2, array($this, 'didReceiveNotifySignal')); pcntl_signal(SIGINT, array($this, 'didReceiveTerminalSignal')); pcntl_signal(SIGTERM, array($this, 'didReceiveTerminalSignal')); @@ -272,6 +273,13 @@ } } + public function didReceiveNotifySignal($signo) { + $pid = $this->childPID; + if ($pid) { + posix_kill($pid, $signo); + } + } + public function didReceiveKeepaliveSignal($signo) { $this->deadline = time() + $this->deadlineTimeout; }