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

Reply via email to