[Libreoffice-commits] online.git: loolwsd/LOOLBroker.cpp loolwsd/LOOLKit.cpp
Ashod Nakashian
ashod.nakashian at collabora.co.uk
Mon Apr 4 04:08:54 UTC 2016
loolwsd/LOOLBroker.cpp | 524 ++-----------------------------------------------
loolwsd/LOOLKit.cpp | 144 -------------
2 files changed, 31 insertions(+), 637 deletions(-)
New commits:
commit c118987dc6e21053024aee3407425e5cc709b0e3
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date: Sun Apr 3 22:31:51 2016 -0400
loolwsd: Removed Broker <-> Kit pipes
Broker is now just a simple spawn-machine.
It only gets requests from WSD to spawn
new kit instances, which it doesn't even
track.
Once a kit instance is initialized, it
connects to WSD with a control WS.
From there on, it's up to WSD to manage
the kit process.
Also was removed the benchmark logic
since it can no longer function.
Change-Id: I1bf56bc6416c9eadafba637276bbb8b3107e5727
Reviewed-on: https://gerrit.libreoffice.org/23790
Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
Tested-by: Ashod Nakashian <ashnakash at gmail.com>
diff --git a/loolwsd/LOOLBroker.cpp b/loolwsd/LOOLBroker.cpp
index 5231eab..c37116a 100644
--- a/loolwsd/LOOLBroker.cpp
+++ b/loolwsd/LOOLBroker.cpp
@@ -32,7 +32,6 @@ typedef int (LokHookPreInit) (const char *install_path, const char *user_profil
const std::string BROKER_SUFIX = ".fifo";
const std::string BROKER_PREFIX = "lokit";
-static int ReaderChild = -1;
static int ReaderBroker = -1;
static std::string LoolkitPath;
@@ -40,127 +39,11 @@ static std::atomic<unsigned> ForkCounter;
static unsigned int ChildCounter = 0;
static int NumPreSpawnedChildren = 1;
-namespace
-{
- class ChildProcess
- {
- public:
- ChildProcess() :
- _pid(-1),
- _writePipe(-1)
- {
- }
-
- ChildProcess(const Poco::Process::PID pid, const int writePipe) :
- _pid(pid),
- _writePipe(writePipe)
- {
- }
-
- ChildProcess(ChildProcess&& other) :
- _pid(other._pid),
- _writePipe(other._writePipe)
- {
- other._pid = -1;
- other._writePipe = -1;
- }
-
- const ChildProcess& operator=(ChildProcess&& other)
- {
- _pid = other._pid;
- other._pid = -1;
- _writePipe = other._writePipe;
- other._writePipe = -1;
-
- return *this;
- }
-
- ~ChildProcess()
- {
- close(true);
- }
-
- void close(const bool rude)
- {
- if (_pid != -1)
- {
- if (kill(_pid, SIGINT) != 0 && rude && kill(_pid, 0) != 0)
- {
- Log::error("Cannot terminate lokit [" + std::to_string(_pid) + "]. Abandoning.");
- }
-
- std::ostringstream message;
- message << "rmdoc" << " "
- << _pid << " "
- << "\n";
- IoUtil::writeFIFO(WriterNotify, message.str());
- _pid = -1;
- }
-
- if (_writePipe != -1)
- {
- ::close(_writePipe);
- _writePipe = -1;
- }
- }
-
- void setUrl(const std::string& url) { _url = url; }
- const std::string& getUrl() const { return _url; }
-
- Poco::Process::PID getPid() const { return _pid; }
- int getWritePipe() const { return _writePipe; }
-
- private:
- std::string _url;
- Poco::Process::PID _pid;
- int _writePipe;
- };
-
- static std::map<Process::PID, std::shared_ptr<ChildProcess>> _childProcesses;
- static std::deque<std::shared_ptr<ChildProcess>> _newChildProcesses;
-
- /// Looks up a child hosting a URL, otherwise returns an empty one.
- /// If neither exist, then returns null.
- std::shared_ptr<ChildProcess> findChild(const std::string& url)
- {
- for (const auto& it : _childProcesses)
- {
- if (it.second->getUrl() == url)
- {
- return it.second;
- }
- }
-
- // Try an empty one.
- if (!_newChildProcesses.empty())
- {
- auto child = _newChildProcesses.front();
- _newChildProcesses.pop_front();
- return child;
- }
-
- return nullptr;
- }
-
- /// Removes a used child process. New ones can't be removed.
- void removeChild(const Process::PID pid, const bool rude)
- {
- const auto it = _childProcesses.find(pid);
- if (it != _childProcesses.end())
- {
- // Close the child resources.
- it->second->close(rude);
- _childProcesses.erase(it);
- }
- }
-}
-
class ChildDispatcher
{
public:
ChildDispatcher() :
- _wsdPipeReader("wsd_pipe_rd", ReaderBroker),
- _childPipeReader("child_pipe_rd", ReaderChild)
+ _wsdPipeReader("wsd_pipe_rd", ReaderBroker)
{
}
@@ -171,104 +54,14 @@ public:
[]() { return TerminationFlag; });
}
- /// Used for benchmarking child initialization.
- bool waitForResponse()
- {
- std::string response;
- if (_childPipeReader.readLine(response, [](){ return TerminationFlag; }) <= 0)
- Log::error("Error reading response to benchmark message from child");
- else
- Log::debug("got response '" + response + "'");
- return response == "started";
- }
-
private:
-
- bool createSession(const std::shared_ptr<ChildProcess>& child, const std::string& session, const std::string& url)
- {
- const std::string message = "session " + session + " " + url + "\n";
- const auto childPid = std::to_string(child->getPid());
- const auto childPipe = child->getWritePipe();
- if (IoUtil::writeFIFO(childPipe, message) < 0)
- {
- Log::error("Error sending session message to child [" + childPid + "].");
- return false;
- }
-
- while (true)
- {
- std::string response;
- if (_childPipeReader.readLine(response, [](){ return TerminationFlag; }) <= 0)
- {
- Log::error("Error reading response to session message from child [" + childPid + "].");
- return false;
- }
-
- Log::debug("Got message from child ! '" + response + "'");
-
- StringTokenizer tokens(response, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
- if (tokens.count() > 0 && tokens[0] != childPid)
- {
- // Not a response from the child in question.
- continue;
- }
-
- return (tokens.count() == 2 && tokens[1] == "ok");
- }
- }
-
void handleInput(const std::string& message)
{
Log::info("Broker command: [" + message + "].");
StringTokenizer tokens(message, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
- if (tokens[0] == "request" && tokens.count() == 3)
- {
- const std::string session = tokens[1];
- const std::string url = tokens[2];
-
- Log::debug("Finding kit for URL [" + url + "] on session [" + session +
- "] in " + std::to_string(_childProcesses.size()) + " childs.");
-
- const auto child = findChild(url);
- if (child)
- {
- const auto childPid = std::to_string(child->getPid());
- const auto isEmptyChild = child->getUrl().empty();
- if (isEmptyChild)
- {
- Log::debug("URL [" + url + "] is not hosted. Using empty child [" + childPid + "].");
- }
- else
- {
- Log::debug("Found URL [" + url + "] hosted on child [" + childPid + "].");
- }
-
- if (createSession(child, session, url))
- {
- child->setUrl(url);
- _childProcesses[child->getPid()] = child;
- Log::debug("Child [" + childPid + "] now hosts [" + url + "] for session [" + session + "].");
- }
- else
- {
- Log::error("Error creating session [" + session + "] for URL [" + url + "] on child [" + childPid + "].");
- }
- }
- else
- {
- Log::info("No children available. Creating more.");
- }
-
- ++ForkCounter;
- }
- else if (tokens[0] == "kill" && tokens.count() == 2)
- {
- Process::PID nPid = static_cast<Process::PID>(std::stoi(tokens[1]));
- removeChild(nPid, true);
- }
- else if (tokens[0] == "spawn" && tokens.count() == 2)
+ if (tokens[0] == "spawn" && tokens.count() == 2)
{
const auto count = std::stoi(tokens[1]);
Log::info("Spawning " + tokens[1] + " childs per request.");
@@ -278,7 +71,6 @@ private:
private:
IoUtil::PipeReader _wsdPipeReader;
- IoUtil::PipeReader _childPipeReader;
};
/// Initializes LibreOfficeKit for cross-fork re-use.
@@ -332,11 +124,9 @@ static int createLibreOfficeKit(const bool sharePages,
const std::string& childRoot,
const std::string& sysTemplate,
const std::string& loTemplate,
- const std::string& loSubPath,
- bool doBenchmark)
+ const std::string& loSubPath)
{
Process::PID childPID;
- int fifoWriter = -1;
const Path pipePath = Path::forDirectory(childRoot + Path::separator() + FIFO_PATH);
const std::string pipeKit = Path(pipePath, BROKER_PREFIX + std::to_string(ChildCounter++) + BROKER_SUFIX).toString();
@@ -363,7 +153,7 @@ static int createLibreOfficeKit(const bool sharePages,
Thread::sleep(std::stoul(std::getenv("SLEEPKITFORDEBUGGER")) * 1000);
}
- lokit_main(childRoot, sysTemplate, loTemplate, loSubPath, pipeKit, doBenchmark);
+ lokit_main(childRoot, sysTemplate, loTemplate, loSubPath, pipeKit);
_exit(Application::EXIT_OK);
}
else
@@ -399,87 +189,10 @@ static int createLibreOfficeKit(const bool sharePages,
}
}
- // open non-blocking to make sure that a broken lokit process will not
- // block the loolbroker forever
- {
- int retries = 5;
- // Note that the use of a condition variable and mutex here is totally pointless as far as I
- // see. There is no code that would notify the condition variable.
- std::mutex fifoMutex;
- std::condition_variable fifoCV;
- std::unique_lock<std::mutex> lock(fifoMutex);
-
- if (std::getenv("SLEEPKITFORDEBUGGER"))
- retries = std::numeric_limits<int>::max();
-
- while(retries && fifoWriter < 0)
- {
- fifoCV.wait_for(
- lock,
- std::chrono::microseconds(80000),
- [&fifoWriter, &pipeKit]
- {
- return (fifoWriter = open(pipeKit.c_str(), O_WRONLY | O_NONBLOCK)) >= 0;
- });
-
- if (fifoWriter < 0)
- {
- Log::debug("Retrying to establish pipe connection: " + std::to_string(retries));
- }
-
- --retries;
- }
- }
-
- if (fifoWriter < 0)
- {
- Log::error("Error: failed to open write pipe [" + pipeKit + "] with kit. Abandoning child.");
- // This is an elaborate way to send a SIGINT to childPID: Construct and immediately destroy
- // a ChildProcess object for it.
- ChildProcess(childPID, -1);
- return -1;
- }
-
- int flags;
- if ((flags = fcntl(fifoWriter, F_GETFL, 0)) < 0)
- {
- Log::error("Error: failed to get pipe flags [" + pipeKit + "].");
- ChildProcess(childPID, -1);
- return -1;
- }
-
- flags &= ~O_NONBLOCK;
- if (fcntl(fifoWriter, F_SETFL, flags) < 0)
- {
- Log::error("Error: failed to set pipe flags [" + pipeKit + "].");
- ChildProcess(childPID, -1);
- return -1;
- }
-
- Log::info() << "Adding Kit #" << ChildCounter << ", PID: " << childPID << Log::end;
-
- _newChildProcesses.emplace_back(std::make_shared<ChildProcess>(childPID, fifoWriter));
+ Log::info() << "Created Kit #" << ChildCounter << ", PID: " << childPID << Log::end;
return childPID;
}
-static bool waitForTerminationChild(const Process::PID pid, int count = CHILD_TIMEOUT_SECS)
-{
- while (count-- > 0)
- {
- int status;
- waitpid(pid, &status, WUNTRACED | WNOHANG);
- if (WIFEXITED(status) || WIFSIGNALED(status))
- {
- Log::info("Child " + std::to_string(pid) + " terminated.");
- return true;
- }
-
- sleep(MAINTENANCE_INTERVAL);
- }
-
- return false;
-}
-
static void printArgumentHelp()
{
std::cout << "Usage: loolbroker [OPTION]..." << std::endl;
@@ -497,58 +210,24 @@ static void printArgumentHelp()
std::cout << "" << std::endl;
std::cout << " Some paramaters are optional:" << std::endl;
std::cout << " --numprespawns=<number> pre-fork at least <number> processes [1]" << std::endl;
- std::cout << " --benchmark pre-fork processes, and print statistics before exiting" << std::endl;
}
-void setupPipes(const std::string &childRoot, bool doBenchmark)
+void setupPipes(const std::string &childRoot)
{
const Path pipePath = Path::forDirectory(childRoot + Path::separator() + FIFO_PATH);
- if (!doBenchmark)
+ const std::string pipeLoolwsd = Path(pipePath, FIFO_LOOLWSD).toString();
+ if ( (ReaderBroker = open(pipeLoolwsd.c_str(), O_RDONLY) ) < 0 )
{
- const std::string pipeLoolwsd = Path(pipePath, FIFO_LOOLWSD).toString();
- if ( (ReaderBroker = open(pipeLoolwsd.c_str(), O_RDONLY) ) < 0 )
- {
- Log::error("Error: failed to open pipe [" + pipeLoolwsd + "] read only. Exiting.");
- std::exit(Application::EXIT_SOFTWARE);
- }
- }
-
- int pipeFlags = O_RDONLY | O_NONBLOCK;
- const std::string pipeBroker = Path(pipePath, FIFO_BROKER).toString();
- if (mkfifo(pipeBroker.c_str(), 0666) < 0 && errno != EEXIST)
- {
- Log::error("Error: Failed to create pipe FIFO [" + FIFO_BROKER + "].");
+ Log::error("Error: failed to open pipe [" + pipeLoolwsd + "] read only. Exiting.");
std::exit(Application::EXIT_SOFTWARE);
}
- if ((ReaderChild = open(pipeBroker.c_str(), pipeFlags) ) < 0)
+ // Open notify pipe
+ const std::string pipeNotify = Path(pipePath, FIFO_ADMIN_NOTIFY).toString();
+ if ((WriterNotify = open(pipeNotify.c_str(), O_WRONLY) ) < 0)
{
- Log::error("Error: pipe opened for reading.");
- std::exit(Application::EXIT_SOFTWARE);
- }
-
- if ((pipeFlags = fcntl(ReaderChild, F_GETFL, 0)) < 0)
- {
- Log::error("Error: failed to get pipe flags [" + FIFO_BROKER + "].");
- std::exit(Application::EXIT_SOFTWARE);
- }
-
- pipeFlags &= ~O_NONBLOCK;
- if (fcntl(ReaderChild, F_SETFL, pipeFlags) < 0)
- {
- Log::error("Error: failed to set pipe flags [" + FIFO_BROKER + "].");
- std::exit(Application::EXIT_SOFTWARE);
- }
-
- if (!doBenchmark)
- {
- // Open notify pipe
- const std::string pipeNotify = Path(pipePath, FIFO_ADMIN_NOTIFY).toString();
- if ((WriterNotify = open(pipeNotify.c_str(), O_WRONLY) ) < 0)
- {
- Log::error("Error: failed to open notify pipe [" + FIFO_ADMIN_NOTIFY + "] for writing.");
- exit(Application::EXIT_SOFTWARE);
- }
+ Log::error("Error: failed to open notify pipe [" + FIFO_ADMIN_NOTIFY + "] for writing.");
+ exit(Application::EXIT_SOFTWARE);
}
}
@@ -573,7 +252,6 @@ int main(int argc, char** argv)
std::string loSubPath;
std::string sysTemplate;
std::string loTemplate;
- bool doBenchmark = false;
for (int i = 0; i < argc; ++i)
{
@@ -609,8 +287,6 @@ int main(int argc, char** argv)
eq = std::strchr(cmd, '=');
ClientPortNumber = std::stoll(std::string(eq+1));
}
- else if (std::strstr(cmd, "--benchmark"))
- doBenchmark = true;
}
LoolkitPath = Poco::Path(argv[0]).parent().toString() + "loolkit";
@@ -629,7 +305,7 @@ int main(int argc, char** argv)
if (!std::getenv("LOK_VIEW_CALLBACK"))
Log::info("Note: LOK_VIEW_CALLBACK is not set.");
- setupPipes(childRoot, doBenchmark);
+ setupPipes(childRoot);
// Initialize LoKit and hope we can fork and save memory by sharing pages.
const bool sharePages = std::getenv("LOK_NO_PREINIT") == nullptr
@@ -643,7 +319,7 @@ int main(int argc, char** argv)
// We must have at least one child, more is created dynamically.
if (createLibreOfficeKit(sharePages, childRoot, sysTemplate,
- loTemplate, loSubPath, doBenchmark) < 0)
+ loTemplate, loSubPath) < 0)
{
Log::error("Error: failed to create children.");
std::exit(Application::EXIT_SOFTWARE);
@@ -672,173 +348,33 @@ int main(int argc, char** argv)
break;
}
- int status;
- const pid_t pid = waitpid(-1, &status, WUNTRACED | WNOHANG);
- if (pid > 0)
- {
- if (WIFEXITED(status))
- {
- Log::info() << "Child process [" << pid << "] exited with code: "
- << WEXITSTATUS(status) << "." << Log::end;
-
- removeChild(pid, false);
- }
- else
- if (WIFSIGNALED(status))
- {
- std::string fate = "died";
-#ifdef WCOREDUMP
- if (WCOREDUMP(status))
- fate = "core-dumped";
-#endif
- Log::error() << "Child process [" << pid << "] " << fate
- << " with " << Util::signalName(WTERMSIG(status))
- << " signal: " << strsignal(WTERMSIG(status))
- << Log::end;
-
- removeChild(pid, false);
- }
- else if (WIFSTOPPED(status))
- {
- Log::info() << "Child process [" << pid << "] stopped with "
- << Util::signalName(WSTOPSIG(status))
- << " signal: " << strsignal(WTERMSIG(status))
- << Log::end;
- }
- else if (WIFCONTINUED(status))
- {
- Log::info() << "Child process [" << pid << "] resumed with SIGCONT."
- << Log::end;
- }
- else
- {
- Log::warn() << "Unknown status returned by waitpid: "
- << std::hex << status << "." << Log::end;
- }
-
- if (WIFEXITED(status) || WIFSIGNALED(status))
- {
- // TODO. recovery files
- const Path childPath = Path::forDirectory(childRoot + Path::separator() + std::to_string(pid));
- Log::info("Removing jail [" + childPath.toString() + "].");
- Util::removeFile(childPath, true);
- }
- }
- else if (pid < 0)
- {
- // No child processes
- if (errno == ECHILD)
- {
- ++ForkCounter;
- }
- else
- {
- Log::error("waitpid failed.");
- }
- }
-
if (ForkCounter > 0)
{
- const auto childCount = _childProcesses.size();
- const int newChildCount = _newChildProcesses.size();
-
// Figure out how many children we need. Always create at least as many
// as configured pre-spawn or one more than requested (whichever is larger).
- int spawn = std::max(static_cast<int>(ForkCounter) + 1, NumPreSpawnedChildren);
- if (spawn > newChildCount)
+ int spawn = ForkCounter;
+ Log::info() << "Creating " << spawn << " new child." << Log::end;
+ size_t newInstances = 0;
+ do
{
- spawn -= newChildCount;
- Log::info() << "Creating " << spawn << " new child. Current total: "
- << childCount << " + " << newChildCount << " (new) = "
- << (childCount + newChildCount) << "." << Log::end;
- size_t newInstances = 0;
- do
+ if (createLibreOfficeKit(sharePages, childRoot, sysTemplate,
+ loTemplate, loSubPath) < 0)
{
- if (createLibreOfficeKit(sharePages, childRoot, sysTemplate,
- loTemplate, loSubPath, doBenchmark) < 0)
- {
- Log::error("Error: fork failed.");
- }
- else
- {
- ++newInstances;
- }
+ Log::error("Error: fork failed.");
+ }
+ else
+ {
+ ++newInstances;
}
- while (--spawn > 0);
-
- // We've done our best. If need more, retrying will bump the counter.
- ForkCounter = (newInstances > ForkCounter ? 0 : ForkCounter - newInstances);
- }
- else
- {
- Log::info() << "Requested " << spawn << " new child. Current total: "
- << childCount << " + " << newChildCount << " (new) = "
- << (childCount + newChildCount) << ". Will not spawn yet." << Log::end;
- ForkCounter = 0;
}
- }
+ while (--spawn > 0);
- if (doBenchmark)
- break;
- }
-
- if (doBenchmark)
- {
- Log::info("loolbroker benchmark - waiting for kits.");
-
- int numSpawned = 0;
- while (numSpawned < NumPreSpawnedChildren)
- {
- if (childDispatcher.waitForResponse())
- numSpawned++;
- Log::info("got children " + std::to_string(numSpawned));
+ // If we need to spawn more, retry later.
+ ForkCounter = (newInstances > ForkCounter ? 0 : ForkCounter - newInstances);
}
-
- Poco::Timestamp::TimeDiff elapsed = startTime.elapsed();
-
- std::cerr << "Time to launch " << NumPreSpawnedChildren << " children: " << (1.0 * elapsed)/Poco::Timestamp::resolution() << std::endl;
- Log::info("loolbroker benchmark complete.");
-
- TerminationFlag = true;
- }
-
- // Terminate child processes.
- for (auto& it : _childProcesses)
- {
- Log::info("Requesting child process " + std::to_string(it.first) + " to terminate.");
- Util::requestTermination(it.first);
}
- for (auto& it : _newChildProcesses)
- {
- Log::info("Requesting child process " + std::to_string(it->getPid()) + " to terminate.");
- Util::requestTermination(it->getPid());
- }
-
- // Wait and kill child processes.
- for (auto& it : _childProcesses)
- {
- if (!waitForTerminationChild(it.first))
- {
- Log::info("Forcing child process " + std::to_string(it.first) + " to terminate.");
- Process::kill(it.first);
- }
- }
-
- for (auto& it : _newChildProcesses)
- {
- if (!waitForTerminationChild(it->getPid()))
- {
- Log::info("Forcing child process " + std::to_string(it->getPid()) + " to terminate.");
- Process::kill(it->getPid());
- }
- }
-
- _childProcesses.clear();
- _newChildProcesses.clear();
-
close(WriterNotify);
- close(ReaderChild);
close(ReaderBroker);
Log::info("Process [loolbroker] finished.");
diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp
index 149ddff..9b012d9 100644
--- a/loolwsd/LOOLKit.cpp
+++ b/loolwsd/LOOLKit.cpp
@@ -66,9 +66,7 @@ using Poco::StringTokenizer;
using Poco::Thread;
using Poco::Util::Application;
-const std::string FIFO_BROKER = "loolbroker.fifo";
const std::string FIFO_ADMIN_NOTIFY = "lool_admin_notify.fifo";
-
static int WriterNotify = -1;
namespace
@@ -882,25 +880,10 @@ void lokit_main(const std::string& childRoot,
try
{
- const int readerBroker = open(pipe.c_str(), O_RDONLY);
- if (readerBroker < 0)
- {
- Log::error("Error: failed to open pipe [" + pipe + "] read only.");
- std::exit(Application::EXIT_SOFTWARE);
- }
-
- const Path pipePath = Path::forDirectory(childRoot + Path::separator() + FIFO_PATH);
- const std::string pipeBroker = Path(pipePath, FIFO_BROKER).toString();
- const int writerBroker = open(pipeBroker.c_str(), O_WRONLY);
- if (writerBroker < 0)
- {
- Log::error("Error: failed to open Broker write pipe [" + FIFO_BROKER + "].");
- std::exit(Application::EXIT_SOFTWARE);
- }
-
if (!doBenchmark)
{
// Open notify pipe
+ const Path pipePath = Path::forDirectory(childRoot + Path::separator() + FIFO_PATH);
const std::string pipeNotify = Path(pipePath, FIFO_ADMIN_NOTIFY).toString();
if ((WriterNotify = open(pipeNotify.c_str(), O_WRONLY) ) < 0)
{
@@ -1015,10 +998,6 @@ void lokit_main(const std::string& childRoot,
}
Log::info("loolkit [" + std::to_string(Process::id()) + "] is ready.");
- if (doBenchmark)
- {
- IoUtil::writeFIFO(writerBroker, "started\n");
- }
// Open websocket connection between the child process and WSD.
Poco::Net::HTTPClientSession cs("127.0.0.1", MASTER_PORT_NUMBER);
@@ -1085,127 +1064,6 @@ void lokit_main(const std::string& childRoot,
},
[](){ return TerminationFlag; },
socketName);
-
- char buffer[READ_BUFFER_SIZE];
- std::string message;
- char* start = nullptr;
- char* end = nullptr;
-
- while (!TerminationFlag)
- {
- if (start == end)
- {
- struct pollfd pollPipeBroker;
- pollPipeBroker.fd = readerBroker;
- pollPipeBroker.events = POLLIN;
- pollPipeBroker.revents = 0;
-
- const int ready = poll(&pollPipeBroker, 1, POLL_TIMEOUT_MS);
- if (ready == 0)
- {
- // time out maintenance
- if (document && document->canDiscard())
- {
- Log::info("Document closed. Flagging for termination.");
- TerminationFlag = true;
- }
- }
- else
- if (ready < 0)
- {
- Log::error("Failed to poll pipe [" + pipe + "].");
- continue;
- }
- else
- if (pollPipeBroker.revents & (POLLIN | POLLPRI))
- {
- const auto bytes = IoUtil::readFIFO(readerBroker, buffer, sizeof(buffer));
- if (bytes < 0)
- {
- start = end = nullptr;
- Log::error("Error reading message from pipe [" + pipe + "].");
- continue;
- }
- start = buffer;
- end = buffer + bytes;
- }
- else
- if (pollPipeBroker.revents & (POLLERR | POLLHUP))
- {
- Log::error("Broken pipe [" + pipe + "] with broker.");
- break;
- }
- }
-
- if (start != end)
- {
- char byteChar = *start++;
- while (start != end && byteChar != '\n')
- {
- message += byteChar;
- byteChar = *start++;
- }
-
- if (byteChar == '\n')
- {
- Log::trace("Recv: " + message);
- StringTokenizer tokens(message, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
- auto response = std::to_string(Process::id()) + " ";
-
- if (TerminationFlag)
- {
- // Too late, we're going down.
- response += "down\n";
- }
- else if (tokens[0] == "session")
- {
- const std::string& sessionId = tokens[1];
- const unsigned intSessionId = Util::decodeId(sessionId);
- const std::string& docKey = tokens[2];
-
- std::string url;
- Poco::URI::decode(docKey, url);
- Log::info("New session [" + sessionId + "] request on url [" + url + "].");
-
- if (!document)
- {
- document = std::make_shared<Document>(loKit, jailId, docKey, url);
- }
-
- // Validate and create session.
- if (url == document->getUrl() &&
- document->createSession(sessionId, intSessionId))
- {
- response += "ok\n";
- }
- else
- {
- response += "bad\n";
- }
- }
- else if (document && document->canDiscard())
- {
- TerminationFlag = true;
- response += "down\n";
- }
- else
- {
- response += "bad unknown token [" + tokens[0] + "]\n";
- }
-
- IoUtil::writeFIFO(writerBroker, response);
-
- // Don't log the CR LF at end
- assert(response.length() > 2);
- assert(response[response.length()-1] == '\n');
- Log::trace("KitToBroker: " + response.substr(0, response.length()-2));
- message.clear();
- }
- }
- }
-
- close(writerBroker);
- close(readerBroker);
}
catch (const Poco::Exception& exc)
{
More information about the Libreoffice-commits
mailing list