[Libreoffice-commits] online.git: loolwsd/ChildProcessSession.cpp loolwsd/LOOLBroker.cpp loolwsd/LOOLWSD.cpp loolwsd/LOOLWSD.hpp loolwsd/MasterProcessSession.cpp loolwsd/MasterProcessSession.hpp

Henry Castro hcastro at collabora.com
Wed Dec 23 09:22:40 PST 2015


 loolwsd/ChildProcessSession.cpp  |   10 -
 loolwsd/LOOLBroker.cpp           |   39 ++--
 loolwsd/LOOLWSD.cpp              |  375 +++++++++++++++++++++------------------
 loolwsd/LOOLWSD.hpp              |    3 
 loolwsd/MasterProcessSession.cpp |   52 +++--
 loolwsd/MasterProcessSession.hpp |    7 
 6 files changed, 280 insertions(+), 206 deletions(-)

New commits:
commit ef9313e3a9bfc727c44c83d09653dda4bc525c5e
Author: Henry Castro <hcastro at collabora.com>
Date:   Sat Dec 19 20:09:48 2015 -0500

    loolwsd: deligating to loolbroker and loolkit
    
    Change-Id: I8499540630373a1bee12a5f58fca3ed701ff6404
    Reviewed-on: https://gerrit.libreoffice.org/20904
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/loolwsd/ChildProcessSession.cpp b/loolwsd/ChildProcessSession.cpp
index 95909af..b74138b 100644
--- a/loolwsd/ChildProcessSession.cpp
+++ b/loolwsd/ChildProcessSession.cpp
@@ -139,10 +139,16 @@ bool ChildProcessSession::handleInput(const char *buffer, int length)
                tokens[0] == "resetselection" ||
                tokens[0] == "saveas");
 
-        if (_docType != "text" && _loKitDocument->pClass->getPart(_loKitDocument) != _clientPart)
         {
-            _loKitDocument->pClass->setPart(_loKitDocument, _clientPart);
+            Poco::Mutex::ScopedLock lock(_mutex);
+
+            _loKitDocument->pClass->setView(_loKitDocument, _viewId);
+            if (_docType != "text" && _loKitDocument->pClass->getPart(_loKitDocument) != _clientPart)
+            {
+                _loKitDocument->pClass->setPart(_loKitDocument, _clientPart);
+            }
         }
+
         if (tokens[0] == "clientzoom")
         {
             return clientZoom(buffer, length, tokens);
diff --git a/loolwsd/LOOLBroker.cpp b/loolwsd/LOOLBroker.cpp
index df77fa8..5a64598 100644
--- a/loolwsd/LOOLBroker.cpp
+++ b/loolwsd/LOOLBroker.cpp
@@ -701,16 +701,16 @@ int main(int argc, char** argv)
 
     const Poco::UInt64 _childId = Util::rng::getNext();
 
-    Path jail = Path::forDirectory(childRoot + Path::separator() + std::to_string(_childId));
-    File(jail).createDirectories();
+    Path jailPath = Path::forDirectory(childRoot + Path::separator() + std::to_string(_childId));
+    File(jailPath).createDirectories();
 
-    Path jailLOInstallation(jail, loSubPath);
+    Path jailLOInstallation(jailPath, loSubPath);
     jailLOInstallation.makeDirectory();
     File(jailLOInstallation).createDirectory();
 
     // Copy (link) LO installation and other necessary files into it from the template
 
-    linkOrCopy(sysTemplate, jail);
+    linkOrCopy(sysTemplate, jailPath);
     linkOrCopy(loTemplate, jailLOInstallation);
 
     // It is necessary to deploy loolkit process to chroot jail.
@@ -719,34 +719,45 @@ int main(int argc, char** argv)
         std::cout << Util::logPrefix() << "loolkit does not exists" << std::endl;
         exit(-1);
     }
-    File("loolkit").copyTo(Path(jail, "/usr/bin").toString());
+    File("loolkit").copyTo(Path(jailPath, "/usr/bin").toString());
+
+    // We need this because sometimes the hostname is not resolved
+    std::vector<std::string> networkFiles = {"/etc/host.conf", "/etc/hosts", "/etc/nsswitch.conf", "/etc/resolv.conf"};
+    for (std::vector<std::string>::iterator it = networkFiles.begin(); it != networkFiles.end(); ++it)
+    {
+       File networkFile(*it);
+       if (networkFile.exists())
+       {
+           networkFile.copyTo(Path(jailPath, "/etc").toString());
+       }
+    }
 
 #ifdef __linux
     // Create the urandom and random devices
-    File(Path(jail, "/dev")).createDirectory();
-    if (mknod((jail.toString() + "/dev/random").c_str(),
+    File(Path(jailPath, "/dev")).createDirectory();
+    if (mknod((jailPath.toString() + "/dev/random").c_str(),
               S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
               makedev(1, 8)) != 0)
     {
         std::cout << Util::logPrefix() +
-            "mknod(" + jail.toString() + "/dev/random) failed: " +
+            "mknod(" + jailPath.toString() + "/dev/random) failed: " +
             strerror(errno) << std::endl;
 
     }
-    if (mknod((jail.toString() + "/dev/urandom").c_str(),
+    if (mknod((jailPath.toString() + "/dev/urandom").c_str(),
               S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
               makedev(1, 9)) != 0)
     {
         std::cout << Util::logPrefix() +
-            "mknod(" + jail.toString() + "/dev/urandom) failed: " +
+            "mknod(" + jailPath.toString() + "/dev/urandom) failed: " +
             strerror(errno) << std::endl;
     }
 #endif
 
-    std::cout << Util::logPrefix() << "loolbroker -> chroot(\"" + jail.toString() + "\")" << std::endl;
-    if (chroot(jail.toString().c_str()) == -1)
+    std::cout << Util::logPrefix() << "loolbroker -> chroot(\"" + jailPath.toString() + "\")" << std::endl;
+    if (chroot(jailPath.toString().c_str()) == -1)
     {
-        std::cout << Util::logPrefix() << "chroot(\"" + jail.toString() + "\") failed: " + strerror(errno) << std::endl;
+        std::cout << Util::logPrefix() << "chroot(\"" + jailPath.toString() + "\") failed: " + strerror(errno) << std::endl;
         exit(-1);
     }
 
@@ -758,6 +769,8 @@ int main(int argc, char** argv)
 
 #ifdef __linux
     dropCapability(CAP_SYS_CHROOT);
+    dropCapability(CAP_MKNOD);
+    dropCapability(CAP_FOWNER);
 #else
     dropCapability();
 #endif
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index 229f78d..41da9bb 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -148,8 +148,172 @@ using Poco::Net::Socket;
 using Poco::ThreadLocal;
 using Poco::Random;
 using Poco::NamedMutex;
+using Poco::ProcessHandle;
 using Poco::URI;
 
+namespace
+{
+    ThreadLocal<std::string> sourceForLinkOrCopy;
+    ThreadLocal<Path> destinationForLinkOrCopy;
+
+    int linkOrCopyFunction(const char *fpath,
+                           const struct stat* /*sb*/,
+                           int typeflag,
+                           struct FTW* /*ftwbuf*/)
+    {
+        if (strcmp(fpath, sourceForLinkOrCopy->c_str()) == 0)
+            return 0;
+
+        assert(fpath[strlen(sourceForLinkOrCopy->c_str())] == '/');
+        const char *relativeOldPath = fpath + strlen(sourceForLinkOrCopy->c_str()) + 1;
+
+#ifdef __APPLE__
+        if (strcmp(relativeOldPath, "PkgInfo") == 0)
+            return 0;
+#endif
+
+        Path newPath(*destinationForLinkOrCopy, Path(relativeOldPath));
+
+        switch (typeflag)
+        {
+        case FTW_F:
+            File(newPath.parent()).createDirectories();
+            if (link(fpath, newPath.toString().c_str()) == -1)
+            {
+                Application::instance().logger().error(Util::logPrefix() +
+                                                       "link(\"" + fpath + "\",\"" + newPath.toString() + "\") failed: " +
+                                                       strerror(errno));
+                exit(1);
+            }
+            break;
+        case FTW_DP:
+            {
+                struct stat st;
+                if (stat(fpath, &st) == -1)
+                {
+                    Application::instance().logger().error(Util::logPrefix() +
+                                                           "stat(\"" + fpath + "\") failed: " +
+                                                           strerror(errno));
+                    return 1;
+                }
+                File(newPath).createDirectories();
+                struct utimbuf ut;
+                ut.actime = st.st_atime;
+                ut.modtime = st.st_mtime;
+                if (utime(newPath.toString().c_str(), &ut) == -1)
+                {
+                    Application::instance().logger().error(Util::logPrefix() +
+                                                           "utime(\"" + newPath.toString() + "\", &ut) failed: " +
+                                                           strerror(errno));
+                    return 1;
+                }
+            }
+            break;
+        case FTW_DNR:
+            Application::instance().logger().error(Util::logPrefix() +
+                                                   "Cannot read directory '" + fpath + "'");
+            return 1;
+        case FTW_NS:
+            Application::instance().logger().error(Util::logPrefix() +
+                                                   "nftw: stat failed for '" + fpath + "'");
+            return 1;
+        case FTW_SLN:
+            Application::instance().logger().information(Util::logPrefix() +
+                                                         "nftw: symlink to nonexistent file: '" + fpath + "', ignored");
+            break;
+        default:
+            assert(false);
+        }
+        return 0;
+    }
+
+    void linkOrCopy(const std::string& source, const Path& destination)
+    {
+        *sourceForLinkOrCopy = source;
+        if (sourceForLinkOrCopy->back() == '/')
+            sourceForLinkOrCopy->pop_back();
+        *destinationForLinkOrCopy = destination;
+        if (nftw(source.c_str(), linkOrCopyFunction, 10, FTW_DEPTH) == -1)
+            Application::instance().logger().error(Util::logPrefix() +
+                                                   "linkOrCopy: nftw() failed for '" + source + "'");
+    }
+
+    void dropCapability(
+#ifdef __linux
+                        cap_value_t capability
+#endif
+                        )
+    {
+#ifdef __linux
+        cap_t caps;
+        cap_value_t cap_list[] = { capability };
+
+        caps = cap_get_proc();
+        if (caps == NULL)
+        {
+            Application::instance().logger().error(Util::logPrefix() + "cap_get_proc() failed: " + strerror(errno));
+            exit(1);
+        }
+
+        if (cap_set_flag(caps, CAP_EFFECTIVE, sizeof(cap_list)/sizeof(cap_list[0]), cap_list, CAP_CLEAR) == -1 ||
+            cap_set_flag(caps, CAP_PERMITTED, sizeof(cap_list)/sizeof(cap_list[0]), cap_list, CAP_CLEAR) == -1)
+        {
+            Application::instance().logger().error(Util::logPrefix() +  "cap_set_flag() failed: " + strerror(errno));
+            exit(1);
+        }
+
+        if (cap_set_proc(caps) == -1)
+        {
+            Application::instance().logger().error(std::string("cap_set_proc() failed: ") + strerror(errno));
+            exit(1);
+        }
+
+        char *capText = cap_to_text(caps, NULL);
+        Application::instance().logger().information(Util::logPrefix() + "Capabilities now: " + capText);
+        cap_free(capText);
+
+        cap_free(caps);
+#endif
+        // We assume that on non-Linux we don't need to be root to be able to hardlink to files we
+        // don't own, so drop root.
+        if (geteuid() == 0 && getuid() != 0)
+        {
+            // The program is setuid root. Not normal on Linux where we use setcap, but if this
+            // needs to run on non-Linux Unixes, setuid root is what it will bneed to be to be able
+            // to do chroot().
+            if (setuid(getuid()) != 0)
+            {
+                Application::instance().logger().error(std::string("setuid() failed: ") + strerror(errno));
+            }
+        }
+#if ENABLE_DEBUG
+        if (geteuid() == 0 && getuid() == 0)
+        {
+#ifdef __linux
+            // Argh, awful hack
+            if (capability == CAP_FOWNER)
+                return;
+#endif
+
+            // Running under sudo, probably because being debugged? Let's drop super-user rights.
+            LOOLWSD::runningAsRoot = true;
+            if (LOOLWSD::uid == 0)
+            {
+                struct passwd *nobody = getpwnam("nobody");
+                if (nobody)
+                    LOOLWSD::uid = nobody->pw_uid;
+                else
+                    LOOLWSD::uid = 65534;
+            }
+            if (setuid(LOOLWSD::uid) != 0)
+            {
+                Application::instance().logger().error(std::string("setuid() failed: ") + strerror(errno));
+            }
+        }
+#endif
+    }
+}
+
 class QueueHandler: public Runnable
 {
 public:
@@ -391,7 +555,7 @@ public:
 
                 do
                 {
-                    char buffer[200000];
+                    char buffer[200000]; //FIXME: Dynamic?
 
                     if ((pollTimeout = ws->poll(waitTime, Socket::SELECT_READ)))
                     {
@@ -752,169 +916,6 @@ void LOOLWSD::displayHelp()
     helpFormatter.format(std::cout);
 }
 
-namespace
-{
-    ThreadLocal<std::string> sourceForLinkOrCopy;
-    ThreadLocal<Path> destinationForLinkOrCopy;
-
-    int linkOrCopyFunction(const char *fpath,
-                           const struct stat* /*sb*/,
-                           int typeflag,
-                           struct FTW* /*ftwbuf*/)
-    {
-        if (strcmp(fpath, sourceForLinkOrCopy->c_str()) == 0)
-            return 0;
-
-        assert(fpath[strlen(sourceForLinkOrCopy->c_str())] == '/');
-        const char *relativeOldPath = fpath + strlen(sourceForLinkOrCopy->c_str()) + 1;
-
-#ifdef __APPLE__
-        if (strcmp(relativeOldPath, "PkgInfo") == 0)
-            return 0;
-#endif
-
-        Path newPath(*destinationForLinkOrCopy, Path(relativeOldPath));
-
-        switch (typeflag)
-        {
-        case FTW_F:
-            File(newPath.parent()).createDirectories();
-            if (link(fpath, newPath.toString().c_str()) == -1)
-            {
-                Application::instance().logger().error(Util::logPrefix() +
-                                                       "link(\"" + fpath + "\",\"" + newPath.toString() + "\") failed: " +
-                                                       strerror(errno));
-                exit(1);
-            }
-            break;
-        case FTW_DP:
-            {
-                struct stat st;
-                if (stat(fpath, &st) == -1)
-                {
-                    Application::instance().logger().error(Util::logPrefix() +
-                                                           "stat(\"" + fpath + "\") failed: " +
-                                                           strerror(errno));
-                    return 1;
-                }
-                File(newPath).createDirectories();
-                struct utimbuf ut;
-                ut.actime = st.st_atime;
-                ut.modtime = st.st_mtime;
-                if (utime(newPath.toString().c_str(), &ut) == -1)
-                {
-                    Application::instance().logger().error(Util::logPrefix() +
-                                                           "utime(\"" + newPath.toString() + "\", &ut) failed: " +
-                                                           strerror(errno));
-                    return 1;
-                }
-            }
-            break;
-        case FTW_DNR:
-            Application::instance().logger().error(Util::logPrefix() +
-                                                   "Cannot read directory '" + fpath + "'");
-            return 1;
-        case FTW_NS:
-            Application::instance().logger().error(Util::logPrefix() +
-                                                   "nftw: stat failed for '" + fpath + "'");
-            return 1;
-        case FTW_SLN:
-            Application::instance().logger().information(Util::logPrefix() +
-                                                         "nftw: symlink to nonexistent file: '" + fpath + "', ignored");
-            break;
-        default:
-            assert(false);
-        }
-        return 0;
-    }
-
-    void linkOrCopy(const std::string& source, const Path& destination)
-    {
-        *sourceForLinkOrCopy = source;
-        if (sourceForLinkOrCopy->back() == '/')
-            sourceForLinkOrCopy->pop_back();
-        *destinationForLinkOrCopy = destination;
-        if (nftw(source.c_str(), linkOrCopyFunction, 10, FTW_DEPTH) == -1)
-            Application::instance().logger().error(Util::logPrefix() +
-                                                   "linkOrCopy: nftw() failed for '" + source + "'");
-    }
-
-    void dropCapability(
-#ifdef __linux
-                        cap_value_t capability
-#endif
-                        )
-    {
-#ifdef __linux
-        cap_t caps;
-        cap_value_t cap_list[] = { capability };
-
-        caps = cap_get_proc();
-        if (caps == NULL)
-        {
-            Application::instance().logger().error(Util::logPrefix() + "cap_get_proc() failed: " + strerror(errno));
-            exit(1);
-        }
-
-        if (cap_set_flag(caps, CAP_EFFECTIVE, sizeof(cap_list)/sizeof(cap_list[0]), cap_list, CAP_CLEAR) == -1 ||
-            cap_set_flag(caps, CAP_PERMITTED, sizeof(cap_list)/sizeof(cap_list[0]), cap_list, CAP_CLEAR) == -1)
-        {
-            Application::instance().logger().error(Util::logPrefix() +  "cap_set_flag() failed: " + strerror(errno));
-            exit(1);
-        }
-
-        if (cap_set_proc(caps) == -1)
-        {
-            Application::instance().logger().error(std::string("cap_set_proc() failed: ") + strerror(errno));
-            exit(1);
-        }
-
-        char *capText = cap_to_text(caps, NULL);
-        Application::instance().logger().information(Util::logPrefix() + "Capabilities now: " + capText);
-        cap_free(capText);
-
-        cap_free(caps);
-#endif
-        // We assume that on non-Linux we don't need to be root to be able to hardlink to files we
-        // don't own, so drop root.
-        if (geteuid() == 0 && getuid() != 0)
-        {
-            // The program is setuid root. Not normal on Linux where we use setcap, but if this
-            // needs to run on non-Linux Unixes, setuid root is what it will bneed to be to be able
-            // to do chroot().
-            if (setuid(getuid()) != 0)
-            {
-                Application::instance().logger().error(std::string("setuid() failed: ") + strerror(errno));
-            }
-        }
-#if ENABLE_DEBUG
-        if (geteuid() == 0 && getuid() == 0)
-        {
-#ifdef __linux
-            // Argh, awful hack
-            if (capability == CAP_FOWNER)
-                return;
-#endif
-
-            // Running under sudo, probably because being debugged? Let's drop super-user rights.
-            LOOLWSD::runningAsRoot = true;
-            if (LOOLWSD::uid == 0)
-            {
-                struct passwd *nobody = getpwnam("nobody");
-                if (nobody)
-                    LOOLWSD::uid = nobody->pw_uid;
-                else
-                    LOOLWSD::uid = 65534;
-            }
-            if (setuid(LOOLWSD::uid) != 0)
-            {
-                Application::instance().logger().error(std::string("setuid() failed: ") + strerror(errno));
-            }
-        }
-#endif
-    }
-}
-
 // Writer, Impress or Calc
 void LOOLWSD::componentMain()
 {
@@ -1208,11 +1209,34 @@ int LOOLWSD::createDesktop()
     return Application::EXIT_OK;
 }
 
-void LOOLWSD::startupDesktop(int nDesktops)
+int LOOLWSD::createBroker()
 {
-    for (int nCntr = nDesktops; nCntr; nCntr--)
+    Process::Args args;
+
+    args.push_back("--losubpath=" + LOOLWSD::loSubPath);
+    args.push_back("--systemplate=" + sysTemplate);
+    args.push_back("--lotemplate=" + loTemplate);
+    args.push_back("--childroot=" + childRoot);
+    args.push_back("--numprespawns=" + std::to_string(_numPreSpawnedChildren));
+
+    std::string executable = Path(Application::instance().commandPath()).parent().toString() + "loolbroker";
+
+    const auto msg = Util::logPrefix() + "Launching broker: " + executable + " "
+                   + Poco::cat(std::string(" "), args.begin(), args.end());
+    Application::instance().logger().information(msg);
+
+    ProcessHandle child = Process::launch(executable, args);
+
+    MasterProcessSession::_childProcesses[child.id()] = child.id();
+
+    return Application::EXIT_OK;
+}
+
+void LOOLWSD::startupBroker(const signed nBrokers)
+{
+    for (signed nCntr = nBrokers; nCntr > 0; --nCntr)
     {
-        if (createDesktop() < 0)
+        if (createBroker() < 0)
             break;
     }
 }
@@ -1274,7 +1298,7 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
 
     _namedMutexLOOL.lock();
 
-    startupDesktop(1);
+    startupBroker(1);
 
 #ifdef __linux
     dropCapability(CAP_SYS_CHROOT);
@@ -1299,6 +1323,12 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
 
     srv2.start();
 
+    if ( (writerBroker = open(FIFO_FILE.c_str(), O_WRONLY) ) < 0 )
+    {
+        std::cout << Util::logPrefix() << "Pipe opened for writing" << strerror(errno) << std::endl;
+        return Application::EXIT_UNAVAILABLE;
+    }
+
     _namedMutexLOOL.unlock();
 
     TestInput input(*this, svs, srv);
@@ -1361,9 +1391,12 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
     threadPool.joinAll();
     threadPool2.joinAll();
 
-    // Clear sessions to pre-spawned child processes that have connected
-    // but are not yet assigned a document to work on.
-    MasterProcessSession::_availableChildSessions.clear();
+    // Terminate child processes
+    for (auto i : MasterProcessSession::_childProcesses)
+    {
+        logger().information(Util::logPrefix() + "Requesting child process " + std::to_string(i.first) + " to terminate");
+        Process::requestTermination(i.first);
+    }
 
     // wait broker process finish
     waitpid(-1, &status, WUNTRACED);
diff --git a/loolwsd/LOOLWSD.hpp b/loolwsd/LOOLWSD.hpp
index 637c246..3f7cfee 100644
--- a/loolwsd/LOOLWSD.hpp
+++ b/loolwsd/LOOLWSD.hpp
@@ -75,6 +75,9 @@ private:
     int  createComponent();
     int  createDesktop();
 
+    void startupBroker(int nBroker);
+    int  createBroker();
+
 
 #if ENABLE_DEBUG
 public:
diff --git a/loolwsd/MasterProcessSession.cpp b/loolwsd/MasterProcessSession.cpp
index fb4af0b..513e200 100644
--- a/loolwsd/MasterProcessSession.cpp
+++ b/loolwsd/MasterProcessSession.cpp
@@ -46,7 +46,7 @@ using Poco::Util::Application;
 
 std::map<Process::PID, UInt64> MasterProcessSession::_childProcesses;
 
-std::set<std::shared_ptr<MasterProcessSession>> MasterProcessSession::_availableChildSessions;
+std::map<Thread::TID, std::shared_ptr<MasterProcessSession>> MasterProcessSession::_availableChildSessions;
 std::mutex MasterProcessSession::_availableChildSessionMutex;
 std::condition_variable MasterProcessSession::_availableChildSessionCV;
 
@@ -202,17 +202,19 @@ bool MasterProcessSession::handleInput(const char *buffer, int length)
             sendTextFrame("error: cmd=child kind=invalid");
             return false;
         }
-        if (tokens.count() != 3)
+        if (tokens.count() != 4)
         {
             sendTextFrame("error: cmd=child kind=syntax");
             return false;
         }
 
         UInt64 childId = std::stoull(tokens[1]);
-        Process::PID pidChild = std::stoull(tokens[2]);
+        Thread::TID tId = std::stoull(tokens[2]);
+        Process::PID pidChild = std::stoull(tokens[3]);
 
         std::unique_lock<std::mutex> lock(_availableChildSessionMutex);
-        _availableChildSessions.insert(shared_from_this());
+        _availableChildSessions.insert(std::pair<Thread::TID, std::shared_ptr<MasterProcessSession>> (tId, shared_from_this()));
+        std::cout << Util::logPrefix() << _kindString << ",Inserted " << this << " id=" << childId << " into _availableChildSessions, size=" << _availableChildSessions.size() << std::endl;
         std::cout << Util::logPrefix() << "Inserted " << this << " id=" << childId << " into _availableChildSessions, size=" << _availableChildSessions.size() << std::endl;
         _childId = childId;
         _pidChild = pidChild;
@@ -543,30 +545,48 @@ void MasterProcessSession::sendTile(const char *buffer, int length, StringTokeni
 
 void MasterProcessSession::dispatchChild()
 {
+    short nRequest = 3;
+    bool  bFound = false;
+
     // Copy document into jail using the fixed name
 
     std::shared_ptr<MasterProcessSession> childSession;
     std::unique_lock<std::mutex> lock(_availableChildSessionMutex);
 
-    std::cout << Util::logPrefix() << "_availableChildSessions size=" << _availableChildSessions.size() << std::endl;
+    std::cout << Util::logPrefix() << "waiting for a child session permission for " << Thread::currentTid() << std::endl;
+    while (nRequest-- && !bFound)
+    {
+        _availableChildSessionCV.wait_for(
+            lock,
+            std::chrono::milliseconds(2000),
+            [&bFound]
+            {
+                return (bFound = _availableChildSessions.find(Thread::currentTid()) != _availableChildSessions.end());
+            });
+
+        if (!bFound)
+        {
+            std::cout << Util::logPrefix() << "trying ..." << nRequest << std::endl;
+            // request again new URL session
+            std::string aMessage = "request " + std::to_string(Thread::currentTid()) + " " + _docURL + "\r\n";
+            Util::writeFIFO(LOOLWSD::writerBroker, aMessage.c_str(), aMessage.length());
+        }
+    }
 
-    if (_availableChildSessions.size() == 0)
+    if ( bFound )
     {
-        std::cout << Util::logPrefix() << "waiting for a child session to become available" << std::endl;
-        _availableChildSessionCV.wait(lock, [] { return _availableChildSessions.size() > 0; });
-        std::cout << Util::logPrefix() << "waiting done" << std::endl;
+        std::cout << Util::logPrefix() << "waiting child session permission, done!" << std::endl;
+        childSession = _availableChildSessions[Thread::currentTid()];
+        _availableChildSessions.erase(Thread::currentTid());
     }
 
-    childSession = *(_availableChildSessions.begin());
-    _availableChildSessions.erase(childSession);
     lock.unlock();
 
-    if (_availableChildSessions.size() == 0 && !LOOLWSD::doTest)
+    if ( !nRequest && !bFound )
     {
-        LOOLWSD::_namedMutexLOOL.lock();
-        std::cout << Util::logPrefix() << "No available child sessions, queue new child session" << std::endl;
-        LOOLWSD::_sharedForkChild.begin()[0] = LOOLWSD::_numPreSpawnedChildren;
-        LOOLWSD::_namedMutexLOOL.unlock();
+        // it cannot get connected.  shutdown.
+        Util::shutdownWebSocket(*_ws);
+        return;
     }
 
     // Assume a valid URI
diff --git a/loolwsd/MasterProcessSession.hpp b/loolwsd/MasterProcessSession.hpp
index ec5ff0d..4b9329a 100644
--- a/loolwsd/MasterProcessSession.hpp
+++ b/loolwsd/MasterProcessSession.hpp
@@ -42,10 +42,6 @@ public:
      */
     std::string getSaveAs();
 
-    // Sessions to pre-spawned child processes that have connected but are not yet assigned a
-    // document to work on.
-    static std::set<std::shared_ptr<MasterProcessSession>> _availableChildSessions;
-
  protected:
     bool invalidateTiles(const char *buffer, int length, Poco::StringTokenizer& tokens);
 
@@ -67,6 +63,9 @@ public:
     // per document being edited (i.e., per child process).
     std::weak_ptr<MasterProcessSession> _peer;
 
+    // Sessions to pre-spawned child processes that have connected but are not yet assigned a
+    // document to work on.
+    static std::map<Poco::Thread::TID, std::shared_ptr<MasterProcessSession>> _availableChildSessions;
     static std::mutex _availableChildSessionMutex;
     static std::condition_variable _availableChildSessionCV;
 


More information about the Libreoffice-commits mailing list