loolwsd/DocumentBroker.hpp | 21 +++++++++++++++++++ loolwsd/LOOLWSD.cpp | 48 ++++++++++++++++++++++++++++++--------------- 2 files changed, 53 insertions(+), 16 deletions(-)
New commits: commit 2b5ecbd945b2d46cc9c7e0bead6e8304e5c31f21 Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> Date: Sun Apr 24 11:56:02 2016 -0400 loolwsd: validate child and spawn new ones before using Change-Id: Icf7c8a2c0fa6c455cea4a65207f1727638169a28 Reviewed-on: https://gerrit.libreoffice.org/24335 Reviewed-by: Ashod Nakashian <ashnak...@gmail.com> Tested-by: Ashod Nakashian <ashnak...@gmail.com> diff --git a/loolwsd/DocumentBroker.hpp b/loolwsd/DocumentBroker.hpp index 9129fec..dcf2d2a 100644 --- a/loolwsd/DocumentBroker.hpp +++ b/loolwsd/DocumentBroker.hpp @@ -20,6 +20,7 @@ #include <map> #include <Poco/URI.h> +#include <Poco/Net/WebSocket.h> #include "IoUtil.hpp" #include "MasterProcessSession.hpp" @@ -95,6 +96,25 @@ public: Poco::Process::PID getPid() const { return _pid; } std::shared_ptr<Poco::Net::WebSocket> getWebSocket() const { return _ws; } + /// Check whether this child is alive and able to respond. + bool isAlive() const + { + try + { + if (_pid > 1 && _ws && kill(_pid, 0) == 0) + { + // We don't care about the response (and shouldn't read here). + _ws->sendFrame("PING", 4, Poco::Net::WebSocket::FRAME_OP_PING); + return true; + } + } + catch (const std::exception& exc) + { + } + + return false; + } + private: Poco::Process::PID _pid; std::shared_ptr<Poco::Net::WebSocket> _ws; @@ -152,6 +172,7 @@ public: const std::string& getDocKey() const { return _docKey; } const std::string& getFilename() const { return _filename; }; TileCache& tileCache() { return *_tileCache; } + bool isAlive() const { return _childProcess && _childProcess->isAlive(); } size_t getSessionsCount() const { std::lock_guard<std::mutex> lock(_mutex); diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp index a0e46ef..ea40a49 100644 --- a/loolwsd/LOOLWSD.cpp +++ b/loolwsd/LOOLWSD.cpp @@ -190,27 +190,43 @@ static std::shared_ptr<ChildProcess> getNewChild() { std::unique_lock<std::mutex> lock(newChildrenMutex); - const int available = newChildren.size(); - int balance = LOOLWSD::NumPreSpawnedChildren; - if (available == 0) + namespace chrono = std::chrono; + const auto startTime = chrono::steady_clock::now(); + do { - Log::error("No available child. Sending spawn request to forkit and failing."); - } - else - { - balance -= available - 1; - } + const int available = newChildren.size(); + int balance = LOOLWSD::NumPreSpawnedChildren; + if (available == 0) + { + Log::error("getNewChild: No available child. Sending spawn request to forkit and failing."); + } + else + { + balance -= available - 1; // Minus the one we'll dispatch just now. + } - forkChildren(balance); + Log::debug("getNewChild: Have " + std::to_string(available) + " children, forking " + std::to_string(balance)); + forkChildren(balance); - const auto timeout = std::chrono::milliseconds(CHILD_TIMEOUT_SECS * 1000); - if (newChildrenCV.wait_for(lock, timeout, [](){ return !newChildren.empty(); })) - { - auto child = newChildren.back(); - newChildren.pop_back(); - return child; + const auto timeout = chrono::milliseconds(CHILD_TIMEOUT_SECS * 1000); + if (newChildrenCV.wait_for(lock, timeout, [](){ return !newChildren.empty(); })) + { + auto child = newChildren.back(); + newChildren.pop_back(); + + // Validate before returning. + if (child && child->isAlive()) + { + Log::debug("getNewChild: Returning new child [" + std::to_string(child->getPid()) + "]."); + return child; + } + + Log::debug("getNewChild: No live child, forking more."); + } } + while (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - startTime).count() < CHILD_TIMEOUT_SECS * 2000); + Log::debug("getNewChild: Timed out while waiting for new child."); return nullptr; } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits