loolwsd/Admin.cpp | 8 + loolwsd/IoUtil.cpp | 170 +++++++++++++++++++++++++++++++++++++++ loolwsd/IoUtil.hpp | 44 ++++++++++ loolwsd/LOOLBroker.cpp | 13 +- loolwsd/LOOLKit.cpp | 13 +- loolwsd/LOOLSession.cpp | 7 - loolwsd/LOOLWSD.cpp | 5 - loolwsd/Makefile.am | 6 - loolwsd/MasterProcessSession.cpp | 5 - loolwsd/Util.cpp | 136 ------------------------------- loolwsd/Util.hpp | 18 ---- 11 files changed, 246 insertions(+), 179 deletions(-)
New commits: commit ce2fabb7338c3a7c3f79fedebe28d71eeda81231 Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> Date: Sun Mar 27 15:22:24 2016 -0400 loolwsd: moved IO utilities into IoUtil file Change-Id: I1e8d5562787134cbb490c38b19d83b7514ec9baa Reviewed-on: https://gerrit.libreoffice.org/23586 Reviewed-by: Ashod Nakashian <ashnak...@gmail.com> Tested-by: Ashod Nakashian <ashnak...@gmail.com> diff --git a/loolwsd/Admin.cpp b/loolwsd/Admin.cpp index 562bb58..be9c93a 100644 --- a/loolwsd/Admin.cpp +++ b/loolwsd/Admin.cpp @@ -34,6 +34,7 @@ #include "Storage.hpp" #include "LOOLProtocol.hpp" #include "LOOLWSD.hpp" +#include "IoUtil.hpp" #include "Util.hpp" using namespace LOOLProtocol; @@ -193,10 +194,11 @@ void AdminRequestHandler::handleWSRequests(HTTPServerRequest& request, HTTPServe { if (std::stoi(tokens[1])) { - Util::writeFIFO(LOOLWSD::BrokerWritePipe, firstLine + " \r\n"); + IoUtil::writeFIFO(LOOLWSD::BrokerWritePipe, firstLine + " \r\n"); } } - catch(std::exception& e) { + catch(std::exception& e) + { Log::warn() << "Could not kill given PID" << Log::end; } } @@ -492,7 +494,7 @@ void Admin::run() Log::info("Thread [" + thread_name + "] started."); - Util::pollPipeForReading(pollPipeNotify, FIFO_NOTIFY, NotifyPipe, + IoUtil::pollPipeForReading(pollPipeNotify, FIFO_NOTIFY, NotifyPipe, [this](std::string& message) { return handleInput(message); } ); _memStatsTimer.cancel(); diff --git a/loolwsd/IoUtil.cpp b/loolwsd/IoUtil.cpp new file mode 100644 index 0000000..7284eeb --- /dev/null +++ b/loolwsd/IoUtil.cpp @@ -0,0 +1,170 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sys/poll.h> +#include <sys/prctl.h> + +#include <cassert> +#include <cstdlib> +#include <cstring> +#include <iomanip> +#include <mutex> +#include <sstream> +#include <string> + +#include <Poco/Exception.h> +#include <Poco/Net/WebSocket.h> +#include <Poco/Thread.h> + +#include "Common.hpp" +#include "IoUtil.hpp" +#include "Util.hpp" + +namespace IoUtil +{ + +void shutdownWebSocket(std::shared_ptr<Poco::Net::WebSocket> ws) +{ + try + { + if (ws) + ws->shutdown(); + } + catch (const Poco::IOException& exc) + { + Log::warn("Util::shutdownWebSocket: IOException: " + exc.message()); + } +} + +ssize_t writeFIFO(int pipe, const char* buffer, ssize_t size) +{ + ssize_t bytes = -1; + ssize_t count = 0; + + while(true) + { + bytes = write(pipe, buffer + count, size - count); + if (bytes < 0) + { + if (errno == EINTR || errno == EAGAIN) + continue; + + count = -1; + break; + } + else if (count + bytes < size) + { + count += bytes; + } + else + { + count += bytes; + break; + } + } + + return count; +} + +ssize_t readFIFO(int pipe, char* buffer, ssize_t size) +{ + ssize_t bytes; + do + { + bytes = read(pipe, buffer, size); + } + while (bytes < 0 && errno == EINTR); + + return bytes; +} + +ssize_t readMessage(int pipe, char* buffer, ssize_t size) +{ + struct pollfd pollPipe; + + pollPipe.fd = pipe; + pollPipe.events = POLLIN; + pollPipe.revents = 0; + + const int nPoll = poll(&pollPipe, 1, CHILD_TIMEOUT_SECS * 1000); + if ( nPoll < 0 ) + return -1; + + if ( nPoll == 0 ) + errno = ETIME; + + if( (pollPipe.revents & POLLIN) != 0 ) + return readFIFO(pipe, buffer, size); + + return -1; +} + +void pollPipeForReading(pollfd& pollPipe, const std::string& targetPipeName , const int& targetPipe, + std::function<void(std::string& message)> handler) +{ + std::string message; + char buffer[READ_BUFFER_SIZE]; + char* start = buffer; + char* end = buffer; + ssize_t bytes = -1; + + while (!TerminationFlag) + { + if (start == end) + { + if (poll(&pollPipe, 1, POLL_TIMEOUT_MS) < 0) + { + Log::error("Failed to poll pipe [" + targetPipeName + "]."); + continue; + } + else if (pollPipe.revents & (POLLIN | POLLPRI)) + { + bytes = readFIFO(targetPipe, buffer, sizeof(buffer)); + if (bytes < 0) + { + start = end = nullptr; + Log::error("Error reading message from pipe [" + targetPipeName + "]."); + continue; + } + start = buffer; + end = buffer + bytes; + } + else if (pollPipe.revents & (POLLERR | POLLHUP)) + { + Log::error("Broken pipe [" + targetPipeName + "] with wsd."); + break; + } + } + + if (start != end) + { + char byteChar = *start++; + while (start != end && byteChar != '\r' && byteChar != '\n') + { + message += byteChar; + byteChar = *start++; + } + + if (byteChar == '\r' && *start == '\n') + { + start++; + Log::debug(targetPipeName + " recv: " + message); + if (message == "eof") + break; + + handler(message); + message.clear(); + } + } + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/loolwsd/IoUtil.hpp b/loolwsd/IoUtil.hpp new file mode 100644 index 0000000..da3db34 --- /dev/null +++ b/loolwsd/IoUtil.hpp @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IOUTIL_HPP +#define INCLUDED_IOUTIL_HPP + +#include <functional> +#include <string> +#include <memory> + +#include <sys/poll.h> + +#include <Poco/Net/WebSocket.h> +#include <Poco/Logger.h> + +namespace IoUtil +{ + /// Call WebSocket::shutdown() ignoring Poco::IOException. + void shutdownWebSocket(std::shared_ptr<Poco::Net::WebSocket> ws); + + ssize_t writeFIFO(int pipe, const char* buffer, ssize_t size); + inline + ssize_t writeFIFO(int pipe, const std::string& message) + { + return writeFIFO(pipe, message.c_str(), message.size()); + } + + ssize_t readFIFO(int pipe, char* buffer, ssize_t size); + + ssize_t readMessage(int pipe, char* buffer, ssize_t size); + + void pollPipeForReading(pollfd& pollPipe, const std::string& targetPipeName , const int& targetPipe, + std::function<void(std::string& message)> handler); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/loolwsd/LOOLBroker.cpp b/loolwsd/LOOLBroker.cpp index 88682e6..59bb30c 100644 --- a/loolwsd/LOOLBroker.cpp +++ b/loolwsd/LOOLBroker.cpp @@ -14,6 +14,7 @@ #include "Common.hpp" #include "Capabilities.hpp" +#include "IoUtil.hpp" #include "Util.hpp" // First include the grist of the helper process - ideally @@ -26,7 +27,7 @@ #define LIB_SOFFICEAPP "lib" "sofficeapp" ".so" #define LIB_MERGED "lib" "mergedlo" ".so" -typedef int (LokHookPreInit) ( const char *install_path, const char *user_profile_path ); +typedef int (LokHookPreInit) (const char *install_path, const char *user_profile_path); using Poco::ProcessHandle; @@ -103,7 +104,7 @@ namespace message << "rmdoc" << " " << _pid << " " << "\r\n"; - Util::writeFIFO(writerNotify, message.str()); + IoUtil::writeFIFO(writerNotify, message.str()); _pid = -1; } @@ -206,7 +207,7 @@ public: { if (_start == _end) { - bytes = Util::readMessage(pipeReader, _buffer, sizeof(_buffer)); + bytes = IoUtil::readMessage(pipeReader, _buffer, sizeof(_buffer)); if ( bytes < 0 ) { _start = _end = nullptr; @@ -248,7 +249,7 @@ public: bool createThread(const Process::PID pid, const std::string& session, const std::string& url) { const std::string message = "thread " + session + " " + url + "\r\n"; - if (Util::writeFIFO(getChildPipe(pid), message) < 0) + if (IoUtil::writeFIFO(getChildPipe(pid), message) < 0) { Log::error("Error sending thread message to child [" + std::to_string(pid) + "]."); return false; @@ -277,7 +278,7 @@ public: { const auto message = "query url \r\n"; std::string response; - if (Util::writeFIFO(it->second->getWritePipe(), message) < 0 || + if (IoUtil::writeFIFO(it->second->getWritePipe(), message) < 0 || getResponseLine(readerChild, response) < 0) { auto log = Log::error(); @@ -387,7 +388,7 @@ public: Log::debug("Thread [" + thread_name + "] started."); - Util::pollPipeForReading(pollPipeBroker, FIFO_LOOLWSD, readerBroker, + IoUtil::pollPipeForReading(pollPipeBroker, FIFO_LOOLWSD, readerBroker, [this](std::string& message) { return handleInput(message); } ); Log::debug("Thread [" + thread_name + "] finished."); diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp index aeb1618..a79f1db 100644 --- a/loolwsd/LOOLKit.cpp +++ b/loolwsd/LOOLKit.cpp @@ -52,6 +52,7 @@ #include "LOKitHelper.hpp" #include "LOOLProtocol.hpp" #include "QueueHandler.hpp" +#include "IoUtil.hpp" #include "Util.hpp" using namespace LOOLProtocol; @@ -655,7 +656,7 @@ private: << Process::id() << " " << _url << " " << "\r\n"; - Util::writeFIFO(writerNotify, message.str()); + IoUtil::writeFIFO(writerNotify, message.str()); if (_multiView) { @@ -707,7 +708,7 @@ private: << Process::id() << " " << sessionId << " " << "\r\n"; - Util::writeFIFO(writerNotify, message.str()); + IoUtil::writeFIFO(writerNotify, message.str()); return _loKitDocument; } @@ -733,7 +734,7 @@ private: << Process::id() << " " << sessionId << " " << "\r\n"; - Util::writeFIFO(writerNotify, message.str()); + IoUtil::writeFIFO(writerNotify, message.str()); Log::info("Session " + sessionId + " is unloading. " + std::to_string(_clientViews) + " views will remain."); @@ -972,7 +973,7 @@ void lokit_main(const std::string& childRoot, else if (pollPipeBroker.revents & (POLLIN | POLLPRI)) { - bytes = Util::readFIFO(readerBroker, buffer, sizeof(buffer)); + bytes = IoUtil::readFIFO(readerBroker, buffer, sizeof(buffer)); if (bytes < 0) { start = end = nullptr; @@ -1056,7 +1057,7 @@ void lokit_main(const std::string& childRoot, response += "bad \r\n"; } - Util::writeFIFO(writerBroker, response); + IoUtil::writeFIFO(writerBroker, response); // Don't log the CR LF at end assert(response.length() > 2); @@ -1099,7 +1100,7 @@ void lokit_main(const std::string& childRoot, message << "rmdoc" << " " << Process::id() << " " << "\r\n"; - Util::writeFIFO(writerNotify, message.str()); + IoUtil::writeFIFO(writerNotify, message.str()); close(writerNotify); Log::info("Process [" + process_name + "] finished."); diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp index da39bba..3272af6 100644 --- a/loolwsd/LOOLSession.cpp +++ b/loolwsd/LOOLSession.cpp @@ -34,6 +34,7 @@ #include "LOOLProtocol.hpp" #include "LOOLSession.hpp" #include "TileCache.hpp" +#include "IoUtil.hpp" #include "Util.hpp" using namespace LOOLProtocol; @@ -65,7 +66,7 @@ LOOLSession::LOOLSession(const std::string& id, const Kind kind, LOOLSession::~LOOLSession() { - Util::shutdownWebSocket(_ws); + IoUtil::shutdownWebSocket(_ws); } void LOOLSession::sendTextFrame(const std::string& text) @@ -166,7 +167,7 @@ void LOOLSession::disconnect(const std::string& reason) else sendTextFrame("disconnect"); _disconnected = true; - Util::shutdownWebSocket(_ws); + IoUtil::shutdownWebSocket(_ws); } } catch (const IOException& exc) @@ -178,7 +179,7 @@ void LOOLSession::disconnect(const std::string& reason) bool LOOLSession::handleDisconnect(StringTokenizer& /*tokens*/) { _disconnected = true; - Util::shutdownWebSocket(_ws); + IoUtil::shutdownWebSocket(_ws); return false; } diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp index b113200..5003a65 100644 --- a/loolwsd/LOOLWSD.cpp +++ b/loolwsd/LOOLWSD.cpp @@ -120,6 +120,7 @@ DEALINGS IN THE SOFTWARE. #include "MasterProcessSession.hpp" #include "QueueHandler.hpp" #include "Storage.hpp" +#include "IoUtil.hpp" #include "Util.hpp" using namespace LOOLProtocol; @@ -602,7 +603,7 @@ private: // Request a kit process for this doc. const std::string aMessage = "request " + id + " " + docKey + "\r\n"; Log::debug("MasterToBroker: " + aMessage.substr(0, aMessage.length() - 2)); - Util::writeFIFO(LOOLWSD::BrokerWritePipe, aMessage); + IoUtil::writeFIFO(LOOLWSD::BrokerWritePipe, aMessage); // For ToClient sessions, we store incoming messages in a queue and have a separate // thread that handles them. This is so that we can empty the queue when we get a @@ -1493,7 +1494,7 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/) threadPool.joinAll(); // Terminate child processes - Util::writeFIFO(LOOLWSD::BrokerWritePipe, "eof\r\n"); + IoUtil::writeFIFO(LOOLWSD::BrokerWritePipe, "eof\r\n"); Log::info("Requesting child process " + std::to_string(brokerPid) + " to terminate"); Util::requestTermination(brokerPid); diff --git a/loolwsd/Makefile.am b/loolwsd/Makefile.am index c141a62..fe54269 100644 --- a/loolwsd/Makefile.am +++ b/loolwsd/Makefile.am @@ -10,7 +10,7 @@ AM_LDFLAGS = -pthread AM_ETAGSFLAGS = --c++-kinds=+p --fields=+iaS --extra=+q -R --totals=yes * AM_CTAGSFLAGS = $(AM_ETAGSFLAGS) -shared_sources = LOOLProtocol.cpp LOOLSession.cpp MessageQueue.cpp Util.cpp +shared_sources = LOOLProtocol.cpp LOOLSession.cpp MessageQueue.cpp IoUtil.cpp Util.cpp loolwsd_SOURCES = LOOLWSD.cpp ChildProcessSession.cpp MasterProcessSession.cpp TileCache.cpp Admin.cpp DocumentBroker.cpp $(shared_sources) @@ -20,7 +20,7 @@ loadtest_SOURCES = LoadTest.cpp Util.cpp LOOLProtocol.cpp connect_SOURCES = Connect.cpp Util.cpp LOOLProtocol.cpp -lokitclient_SOURCES = LOKitClient.cpp Util.cpp +lokitclient_SOURCES = LOKitClient.cpp IoUtil.cpp Util.cpp broker_shared_sources = ChildProcessSession.cpp $(shared_sources) @@ -33,7 +33,7 @@ loolmap_SOURCES = loolmap.c noinst_HEADERS = LOKitHelper.hpp LOOLProtocol.hpp LOOLSession.hpp MasterProcessSession.hpp ChildProcessSession.hpp \ LOOLWSD.hpp LoadTest.hpp MessageQueue.hpp TileCache.hpp Util.hpp Png.hpp Common.hpp Capabilities.hpp \ Rectangle.hpp QueueHandler.hpp Admin.hpp Auth.hpp Storage.hpp AdminModel.hpp DocumentBroker.hpp \ - FileServer.hpp \ + FileServer.hpp IoUtil.hpp \ bundled/include/LibreOfficeKit/LibreOfficeKit.h bundled/include/LibreOfficeKit/LibreOfficeKitEnums.h \ bundled/include/LibreOfficeKit/LibreOfficeKitInit.h bundled/include/LibreOfficeKit/LibreOfficeKitTypes.h diff --git a/loolwsd/MasterProcessSession.cpp b/loolwsd/MasterProcessSession.cpp index 0fbf70c..459bdc7 100644 --- a/loolwsd/MasterProcessSession.cpp +++ b/loolwsd/MasterProcessSession.cpp @@ -21,6 +21,7 @@ #include "Rectangle.hpp" #include "Storage.hpp" #include "TileCache.hpp" +#include "IoUtil.hpp" #include "Util.hpp" using namespace LOOLProtocol; @@ -752,7 +753,7 @@ void MasterProcessSession::dispatchChild() // request again new URL session const std::string message = "request " + getId() + " " + _docBroker->getDocKey() + "\r\n"; Log::trace("MasterToBroker: " + message.substr(0, message.length()-2)); - Util::writeFIFO(LOOLWSD::BrokerWritePipe, message); + IoUtil::writeFIFO(LOOLWSD::BrokerWritePipe, message); } } @@ -768,7 +769,7 @@ void MasterProcessSession::dispatchChild() if (retries < 0 && !isFound) { Log::error(getName() + ": Failed to connect to child. Shutting down socket."); - Util::shutdownWebSocket(_ws); + IoUtil::shutdownWebSocket(_ws); return; } diff --git a/loolwsd/Util.cpp b/loolwsd/Util.cpp index 477cffd..44cee5c 100644 --- a/loolwsd/Util.cpp +++ b/loolwsd/Util.cpp @@ -282,19 +282,6 @@ namespace Util return true; } - void shutdownWebSocket(std::shared_ptr<Poco::Net::WebSocket> ws) - { - try - { - if (ws) - ws->shutdown(); - } - catch (const Poco::IOException& exc) - { - Log::warn("Util::shutdownWebSocket: IOException: " + exc.message()); - } - } - std::string signalName(const int signo) { switch (signo) @@ -355,69 +342,6 @@ namespace Util } } - ssize_t writeFIFO(int pipe, const char* buffer, ssize_t size) - { - ssize_t bytes = -1; - ssize_t count = 0; - - while(true) - { - bytes = write(pipe, buffer + count, size - count); - if (bytes < 0) - { - if (errno == EINTR || errno == EAGAIN) - continue; - - count = -1; - break; - } - else if (count + bytes < size) - { - count += bytes; - } - else - { - count += bytes; - break; - } - } - - return count; - } - - ssize_t readFIFO(int pipe, char* buffer, ssize_t size) - { - ssize_t bytes; - do - { - bytes = read(pipe, buffer, size); - } - while (bytes < 0 && errno == EINTR); - - return bytes; - } - - ssize_t readMessage(int pipe, char* buffer, ssize_t size) - { - struct pollfd pollPipe; - - pollPipe.fd = pipe; - pollPipe.events = POLLIN; - pollPipe.revents = 0; - - const int nPoll = poll(&pollPipe, 1, CHILD_TIMEOUT_SECS * 1000); - if ( nPoll < 0 ) - return -1; - - if ( nPoll == 0 ) - errno = ETIME; - - if( (pollPipe.revents & POLLIN) != 0 ) - return readFIFO(pipe, buffer, size); - - return -1; - } - static void handleTerminationSignal(const int signal) { @@ -557,66 +481,6 @@ namespace Util } } - void pollPipeForReading(pollfd& pollPipe, const std::string& targetPipeName , const int& targetPipe, - std::function<void(std::string& message)> handler) - { - std::string message; - char buffer[READ_BUFFER_SIZE]; - char* start = buffer; - char* end = buffer; - ssize_t bytes = -1; - - while (!TerminationFlag) - { - if (start == end) - { - if (poll(&pollPipe, 1, POLL_TIMEOUT_MS) < 0) - { - Log::error("Failed to poll pipe [" + targetPipeName + "]."); - continue; - } - else if (pollPipe.revents & (POLLIN | POLLPRI)) - { - bytes = Util::readFIFO(targetPipe, buffer, sizeof(buffer)); - if (bytes < 0) - { - start = end = nullptr; - Log::error("Error reading message from pipe [" + targetPipeName + "]."); - continue; - } - start = buffer; - end = buffer + bytes; - } - else if (pollPipe.revents & (POLLERR | POLLHUP)) - { - Log::error("Broken pipe [" + targetPipeName + "] with wsd."); - break; - } - } - - if (start != end) - { - char byteChar = *start++; - while (start != end && byteChar != '\r' && byteChar != '\n') - { - message += byteChar; - byteChar = *start++; - } - - if (byteChar == '\r' && *start == '\n') - { - start++; - Log::debug(targetPipeName + " recv: " + message); - if (message == "eof") - break; - - handler(message); - message.clear(); - } - } - } - } - unsigned getMemoryUsage(Poco::Process::PID nPid) { //TODO: Instead of RSS, return PSS diff --git a/loolwsd/Util.hpp b/loolwsd/Util.hpp index c496287..ae3f938 100644 --- a/loolwsd/Util.hpp +++ b/loolwsd/Util.hpp @@ -14,7 +14,6 @@ #include <sstream> #include <functional> #include <memory> -#include <sys/poll.h> #include <Poco/File.h> #include <Poco/Path.h> @@ -74,20 +73,6 @@ namespace Util int bufferWidth, int bufferHeight, std::vector<char>& output, LibreOfficeKitTileMode mode); - /// Call WebSocket::shutdown() ignoring Poco::IOException. - void shutdownWebSocket(std::shared_ptr<Poco::Net::WebSocket> ws); - - ssize_t writeFIFO(int pipe, const char* buffer, ssize_t size); - inline - ssize_t writeFIFO(int pipe, const std::string& message) - { - return writeFIFO(pipe, message.c_str(), message.size()); - } - - ssize_t readFIFO(int pipe, char* buffer, ssize_t size); - - ssize_t readMessage(int pipe, char* buffer, ssize_t size); - /// Safely remove a file or directory. /// Supresses exception when the file is already removed. /// This can happen when there is a race (unavoidable) or when @@ -141,9 +126,6 @@ namespace Util void requestTermination(const Poco::Process::PID& pid); - void pollPipeForReading(pollfd& pollPipe, const std::string& targetPipeName , const int& targetPipe, - std::function<void(std::string& message)> handler); - unsigned getMemoryUsage(Poco::Process::PID nPid); }; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits