summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/processmanager.php84
-rw-r--r--lib/spawningdaemon.php32
2 files changed, 116 insertions, 0 deletions
diff --git a/lib/processmanager.php b/lib/processmanager.php
new file mode 100644
index 000000000..6032bfc5c
--- /dev/null
+++ b/lib/processmanager.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * i/o manager to watch for a dead parent process
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category QueueManager
+ * @package StatusNet
+ * @author Brion Vibber <brion@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ProcessManager extends IoManager
+{
+ protected $socket;
+
+ public static function get()
+ {
+ throw new Exception("Must pass ProcessManager per-instance");
+ }
+
+ public function __construct($socket)
+ {
+ $this->socket = $socket;
+ }
+
+ /**
+ * Tell the i/o queue master if and how we can handle multi-site
+ * processes.
+ *
+ * Return one of:
+ * IoManager::SINGLE_ONLY
+ * IoManager::INSTANCE_PER_SITE
+ * IoManager::INSTANCE_PER_PROCESS
+ */
+ public static function multiSite()
+ {
+ return IoManager::INSTANCE_PER_PROCESS;
+ }
+
+ /**
+ * We won't get any input on it, but if it's broken we'll
+ * know something's gone horribly awry.
+ *
+ * @return array of resources
+ */
+ function getSockets()
+ {
+ return array($this->socket);
+ }
+
+ /**
+ * See if the parent died and request a shutdown...
+ *
+ * @param resource $socket
+ * @return boolean success
+ */
+ function handleInput($socket)
+ {
+ if (feof($socket)) {
+ common_log(LOG_INFO, "Parent process exited; shutting down child.");
+ $this->master->requestShutdown();
+ }
+ return true;
+ }
+}
+
diff --git a/lib/spawningdaemon.php b/lib/spawningdaemon.php
index fd9ae4355..2f9f6e32e 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();
@@ -129,6 +131,34 @@ abstract class SpawningDaemon extends Daemon
}
/**
+ * 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.
*
@@ -152,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();