X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=lib%2Fspawningdaemon.php;h=ea09b6fb2f3016f67553cc683b254b537c9da1f6;hb=37cf7c0e8ccaffb11b743da45eaea4a2897bad94;hp=b1961d68801c308fc25429a4cee80b028439f72d;hpb=5e1a9ad04d4e10ee44881a26ea72c9a80f748188;p=quix0rs-gnu-social.git diff --git a/lib/spawningdaemon.php b/lib/spawningdaemon.php index b1961d6880..ea09b6fb2f 100644 --- a/lib/spawningdaemon.php +++ b/lib/spawningdaemon.php @@ -71,6 +71,8 @@ abstract class SpawningDaemon extends Daemon */ function run() { + $this->initPipes(); + $children = array(); for ($i = 1; $i <= $this->threads; $i++) { $pid = pcntl_fork(); @@ -83,24 +85,31 @@ abstract class SpawningDaemon extends Daemon $this->log(LOG_INFO, "Spawned thread $i as pid $pid"); $children[$i] = $pid; } + sleep(common_config('queue', 'spawndelay')); } $this->log(LOG_INFO, "Waiting for children to complete."); while (count($children) > 0) { $status = null; $pid = pcntl_wait($status); - if ($pid > 0 && pcntl_wifexited($status)) { - $exitCode = pcntl_wexitstatus($status); - + if ($pid > 0) { $i = array_search($pid, $children); if ($i === false) { - $this->log(LOG_ERR, "Unrecognized child pid $pid exited with status $exitCode"); + $this->log(LOG_ERR, "Ignoring exit of unrecognized child pid $pid"); continue; } + if (pcntl_wifexited($status)) { + $exitCode = pcntl_wexitstatus($status); + $info = "status $exitCode"; + } else if (pcntl_wifsignaled($status)) { + $exitCode = self::EXIT_ERR; + $signal = pcntl_wtermsig($status); + $info = "signal $signal"; + } unset($children[$i]); if ($this->shouldRespawn($exitCode)) { - $this->log(LOG_INFO, "Thread $i pid $pid exited with status $exitCode; respawing."); + $this->log(LOG_INFO, "Thread $i pid $pid exited with $info; respawing."); $pid = pcntl_fork(); if ($pid < 0) { @@ -111,6 +120,7 @@ abstract class SpawningDaemon extends Daemon $this->log(LOG_INFO, "Respawned thread $i as pid $pid"); $children[$i] = $pid; } + sleep(common_config('queue', 'spawndelay')); } else { $this->log(LOG_INFO, "Thread $i pid $pid exited with status $exitCode; closing out thread."); } @@ -120,6 +130,34 @@ abstract class SpawningDaemon extends Daemon return true; } + /** + * Create an IPC socket pair which child processes can use to detect + * if the parent process has been killed. + */ + function initPipes() + { + $sockets = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, 0); + if ($sockets) { + $this->parentWriter = $sockets[0]; + $this->parentReader = $sockets[1]; + } else { + $this->log(LOG_ERROR, "Couldn't create inter-process sockets"); + exit(1); + } + } + + /** + * Build an IOManager that simply ensures that we have a connection + * to the parent process open. If it breaks, the child process will + * die. + * + * @return ProcessManager + */ + public function processManager() + { + return new ProcessManager($this->parentReader); + } + /** * Determine whether to respawn an exited subprocess based on its exit code. * Otherwise we'll respawn all exits by default. @@ -144,6 +182,8 @@ abstract class SpawningDaemon extends Daemon */ protected function initAndRunChild($thread) { + // Close the writer end of our parent<->children pipe. + fclose($this->parentWriter); $this->set_id($this->get_id() . "." . $thread); $this->resetDb(); $exitCode = $this->runThread(); @@ -164,7 +204,7 @@ abstract class SpawningDaemon extends Daemon // Reconnect main memcached, or threads will stomp on // each other and corrupt their requests. - $cache = common_memcache(); + $cache = Cache::instance(); if ($cache) { $cache->reconnect(); }