[Libreoffice-commits] online.git: Branch 'feature/lifecycle' - 18 commits - loleaflet/README loolwsd/ChildProcessSession.cpp loolwsd/ChildProcessSession.hpp loolwsd/configure.ac loolwsd/.gitignore loolwsd/LOKitHelper.hpp loolwsd/LOOLBroker.cpp loolwsd/LOOLKit.cpp loolwsd/loolmap.c loolwsd/LOOLSession.cpp loolwsd/LOOLSession.hpp loolwsd/LOOLWSD.cpp loolwsd/LOOLWSD.hpp loolwsd/loolwsd-systemplate-setup loolwsd/Makefile.am loolwsd/MasterProcessSession.cpp loolwsd/MasterProcessSession.hpp loolwsd/MessageQueue.cpp loolwsd/MessageQueue.hpp loolwsd/TileCache.cpp loolwsd/Util.cpp loolwsd/Util.hpp

Ashod Nakashian (via logerrit) logerrit at kemper.freedesktop.org
Sat Dec 7 01:50:43 UTC 2019


Rebased ref, commits from common ancestor:
commit ff1bb35b6a99155e9ea58853d7c7c3dc5acc9031
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Wed Dec 23 09:56:46 2015 -0500
Commit:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Wed Dec 23 09:56:46 2015 -0500

    loolwsd: fixes to loolmap
    
    Change-Id: I58ce3dbbd6bbd1e3eb860ba6c3044ba4a61e281d

diff --git a/loolwsd/loolmap.c b/loolwsd/loolmap.c
index 08b149a2a..21792b9d8 100644
--- a/loolwsd/loolmap.c
+++ b/loolwsd/loolmap.c
@@ -1,6 +1,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <errno.h>
+#include <error.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -120,15 +121,15 @@ static void total_smaps(unsigned proc_id, const char *file, const char *cmdline)
     error(EXIT_FAILURE, errno, "%s\n", cmdline);
 
   printf("%s\n", cmdline);
-  printf("Process ID    :%20ld\n", proc_id);
+  printf("Process ID    :%20d\n", proc_id);
   printf("--------------------------------------\n");
-  printf("Shared Clean  :%20ld kB\n", total_shared_clean);
-  printf("Shared Dirty  :%20ld kB\n", total_shared_dirty);
-  printf("Private Clean :%20ld kB\n", total_private_clean);
-  printf("Private Dirty :%20ld kB\n", total_private_dirty);
+  printf("Shared Clean  :%20lld kB\n", total_shared_clean);
+  printf("Shared Dirty  :%20lld kB\n", total_shared_dirty);
+  printf("Private Clean :%20lld kB\n", total_private_clean);
+  printf("Private Dirty :%20lld kB\n", total_private_dirty);
   printf("--------------------------------------\n");
-  printf("Shared        :%20ld kB\n", total_shared_clean + total_shared_dirty);
-  printf("Private       :%20ld kB\n\n", total_private_clean + total_private_dirty);
+  printf("Shared        :%20lld kB\n", total_shared_clean + total_shared_dirty);
+  printf("Private       :%20lld kB\n\n", total_private_clean + total_private_dirty);
 }
 
 int main(int argc, char **argv)
@@ -145,7 +146,7 @@ int main(int argc, char **argv)
   getopt(argc, argv, "");
 
   if (argc != 2)
-    error(EXIT_FAILURE, EINVAL);
+    error(EXIT_FAILURE, EINVAL, "incorrect arguments");
 
   root_proc = opendir("/proc");
   if (!root_proc)
@@ -154,7 +155,7 @@ int main(int argc, char **argv)
   while ( ( dir_proc = readdir(root_proc) ) )
   {
     if ( !dir_proc && !dir_proc->d_name )
-      error(EXIT_FAILURE, ENOTDIR );
+      error(EXIT_FAILURE, ENOTDIR, "bad dir");
 
     if ( *dir_proc->d_name > '0' && *dir_proc->d_name <= '9' )
     {
@@ -165,13 +166,15 @@ int main(int argc, char **argv)
           !strstr(cmdline, argv[0]) )
       {
         snprintf(path_proc, sizeof(path_proc), "/proc/%s/%s", dir_proc->d_name, "smaps");
-        total_smaps(pid_proc, path_proc, cmdline);
-      }
+     total_smaps(pid_proc, path_proc, cmdline);
+   }
     }
   }
 
   if ( errno )
-    error(EXIT_FAILURE, errno);
+    error(EXIT_FAILURE, errno, "fail");
 
   return EXIT_SUCCESS;
 }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 48b1aa328f469514319c9d41e1360c76120b7d2c
Author:     Henry Castro <hcastro at collabora.com>
AuthorDate: Wed Dec 23 09:55:56 2015 -0500
Commit:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Wed Dec 23 09:55:56 2015 -0500

    loolwsd: merged loolmap
    
    Change-Id: I43845ce5f45c01a67db32ab136ad96b70bc31217

diff --git a/loolwsd/.gitignore b/loolwsd/.gitignore
index 1461eea5d..a50e3e6a4 100644
--- a/loolwsd/.gitignore
+++ b/loolwsd/.gitignore
@@ -13,6 +13,7 @@
 /config.log
 /config.status
 /configure
+/compile
 /depcomp
 /install-sh
 /missing
@@ -20,6 +21,7 @@
 /systemplate
 /test-driver
 /jails
+/loolwsd.spec
 
 *.o
 *.exe
@@ -33,6 +35,7 @@ loadtest
 loolwsd
 loolkit
 loolbroker
+loolmap
 sockettransporttest
 
 # Debug output
diff --git a/loolwsd/Makefile.am b/loolwsd/Makefile.am
index d1f76cbc2..02fe17601 100644
--- a/loolwsd/Makefile.am
+++ b/loolwsd/Makefile.am
@@ -1,6 +1,6 @@
 SUBDIRS = test
 
-bin_PROGRAMS = loolwsd loolbroker loolkit
+bin_PROGRAMS = loolwsd loolbroker loolkit loolmap
 
 dist_bin_SCRIPTS = loolwsd-systemplate-setup
 
@@ -25,6 +25,8 @@ loolkit_SOURCES = LOOLKit.cpp $(broker_shared_sources)
 
 loolbroker_SOURCES = LOOLBroker.cpp $(broker_shared_sources)
 
+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 \
                  bundled/include/LibreOfficeKit/LibreOfficeKit.h bundled/include/LibreOfficeKit/LibreOfficeKitEnums.h \
                  bundled/include/LibreOfficeKit/LibreOfficeKitInit.h bundled/include/LibreOfficeKit/LibreOfficeKitTypes.h
diff --git a/loolwsd/configure.ac b/loolwsd/configure.ac
index dce87dcb7..fe58ce892 100644
--- a/loolwsd/configure.ac
+++ b/loolwsd/configure.ac
@@ -13,6 +13,7 @@ AC_CONFIG_HEADERS([config.h])
 
 # Checks for programs.
 AC_PROG_CXX
+AC_PROG_CC
 
 AC_LANG_PUSH([C++])
 
diff --git a/loolwsd/loolmap.c b/loolwsd/loolmap.c
new file mode 100644
index 000000000..08b149a2a
--- /dev/null
+++ b/loolwsd/loolmap.c
@@ -0,0 +1,177 @@
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <locale.h>
+
+#define MAP_SIZE 20
+#define PATH_SIZE 64
+#define BUFFER_SIZE 9600
+
+static int read_buffer( char *buffer, unsigned size,
+                        const char *file, char sep )
+{
+  int file_desc;
+  unsigned total_bytes = 0;
+
+  file_desc = open(file, O_RDONLY);
+  if(file_desc == -1)
+    return 0;
+
+  for(;;)
+  {
+    ssize_t number_bytes = read( file_desc,
+                                 buffer + total_bytes,
+                                 size - total_bytes );
+    if(number_bytes == -1)
+    {
+      if(errno==EINTR)
+        continue;
+      break;
+    }
+
+    total_bytes += number_bytes;
+    if(total_bytes == size)
+    {
+      --total_bytes;
+      break;
+    }
+
+    if(number_bytes==0)
+      break;  // EOF
+  }
+
+  close(file_desc);
+
+  if(total_bytes)
+  {
+    int i=total_bytes;
+
+    while(i--)
+      if(buffer[i]=='\n' || buffer[i]=='\0')
+        buffer[i]=sep;
+
+    if(buffer[total_bytes-1]==' ')
+      buffer[total_bytes-1]='\0';
+  }
+
+  buffer[total_bytes] = '\0';
+  return total_bytes;
+}
+
+static void total_smaps(unsigned proc_id, const char *file, const char *cmdline)
+{
+  FILE *file_pointer;
+  char buffer[BUFFER_SIZE];
+
+  unsigned long long private_dirty = 0ull;
+  unsigned long long private_clean = 0ull;
+  unsigned long long shared_dirty = 0ull;
+  unsigned long long shared_clean = 0ull;
+  unsigned long long total_private_dirty = 0ull;
+  unsigned long long total_private_clean = 0ull;
+  unsigned long long total_shared_dirty = 0ull;
+  unsigned long long total_shared_clean = 0ull;
+  unsigned long long smap_value;
+  char smap_key[MAP_SIZE];
+
+  if ((file_pointer = fopen(file, "r")) == NULL)
+    error(EXIT_FAILURE, errno, "%s", file);
+
+  while (fgets(buffer, sizeof(buffer), file_pointer))
+  {
+    if (buffer[0] >= 'A' && buffer[0] <= 'Z')
+    {
+      if (sscanf(buffer, "%20[^:]: %llu", smap_key, &smap_value) == 2)
+      {
+        if (strncmp("Shared_Dirty", smap_key, 12) == 0)
+        {
+          shared_dirty = smap_value;
+          total_shared_dirty += smap_value;
+          continue;
+        }
+        if (strncmp("Shared_Clean", smap_key, 12) == 0)
+        {
+          shared_clean = smap_value;
+          total_shared_clean += smap_value;
+          continue;
+        }
+        if (strncmp("Private_Dirty", smap_key, 13) == 0)
+        {
+          private_dirty = smap_value;
+          total_private_dirty += smap_value;
+          continue;
+        }
+        if (strncmp("Private_Clean", smap_key, 13) == 0)
+        {
+          private_clean = smap_value;
+          total_private_clean += smap_value;
+          continue;
+        }
+      }
+    }
+  }
+
+  if ( errno )
+    error(EXIT_FAILURE, errno, "%s\n", cmdline);
+
+  printf("%s\n", cmdline);
+  printf("Process ID    :%20ld\n", proc_id);
+  printf("--------------------------------------\n");
+  printf("Shared Clean  :%20ld kB\n", total_shared_clean);
+  printf("Shared Dirty  :%20ld kB\n", total_shared_dirty);
+  printf("Private Clean :%20ld kB\n", total_private_clean);
+  printf("Private Dirty :%20ld kB\n", total_private_dirty);
+  printf("--------------------------------------\n");
+  printf("Shared        :%20ld kB\n", total_shared_clean + total_shared_dirty);
+  printf("Private       :%20ld kB\n\n", total_private_clean + total_private_dirty);
+}
+
+int main(int argc, char **argv)
+{
+  DIR *root_proc;
+  struct dirent *dir_proc;
+
+  unsigned pid_curr;
+  unsigned pid_proc;
+  char path_proc[PATH_SIZE];
+  char cmdline[BUFFER_SIZE];
+
+  setlocale (LC_ALL, "");
+  getopt(argc, argv, "");
+
+  if (argc != 2)
+    error(EXIT_FAILURE, EINVAL);
+
+  root_proc = opendir("/proc");
+  if (!root_proc)
+    error(EXIT_FAILURE, errno, "%s", "/proc");
+
+  while ( ( dir_proc = readdir(root_proc) ) )
+  {
+    if ( !dir_proc && !dir_proc->d_name )
+      error(EXIT_FAILURE, ENOTDIR );
+
+    if ( *dir_proc->d_name > '0' && *dir_proc->d_name <= '9' )
+    {
+      pid_proc = strtoul(dir_proc->d_name, NULL, 10);
+      snprintf(path_proc, sizeof(path_proc), "/proc/%s/%s", dir_proc->d_name, "cmdline");
+      if (read_buffer(cmdline, sizeof(cmdline), path_proc, ' ') &&
+          strstr(cmdline, argv[1]) &&
+          !strstr(cmdline, argv[0]) )
+      {
+        snprintf(path_proc, sizeof(path_proc), "/proc/%s/%s", dir_proc->d_name, "smaps");
+        total_smaps(pid_proc, path_proc, cmdline);
+      }
+    }
+  }
+
+  if ( errno )
+    error(EXIT_FAILURE, errno);
+
+  return EXIT_SUCCESS;
+}
commit 27487e7d121bed52aed6f598e7da555c7543758e
Author:     Henry Castro <hcastro at collabora.com>
AuthorDate: Mon Dec 21 09:54:52 2015 -0500
Commit:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Wed Dec 23 09:50:05 2015 -0500

    loolwsd: Merged improved lifecycle prototype
    
    Enabled the broker and kit processes.
    
    Change-Id: I9afedbccac35732ffe846494cae8135d306e6311

diff --git a/loolwsd/ChildProcessSession.cpp b/loolwsd/ChildProcessSession.cpp
index dd56da0a5..cf75086f6 100644
--- a/loolwsd/ChildProcessSession.cpp
+++ b/loolwsd/ChildProcessSession.cpp
@@ -211,114 +211,15 @@ extern "C"
 {
     static void myCallback(int nType, const char* pPayload, void* pData)
     {
-        ChildProcessSession *srv = reinterpret_cast<ChildProcessSession *>(pData);
+        /*pid_t tid = syscall(SYS_gettid);
+        std::cout << tid << " callbackWorker : " << priv->m_nViewId << " " << std::string(callbackTypeToString(nType)) << " " << std::string(pPayload ? pPayload : "(nil)") << std::endl;*/
 
-        switch ((LibreOfficeKitCallbackType) nType)
-        {
-        case LOK_CALLBACK_INVALIDATE_TILES:
-            {
-                int curPart = srv->_loKitDocument->pClass->getPart(srv->_loKitDocument);
-                srv->sendTextFrame("curpart: part=" + std::to_string(curPart));
-                if (srv->_docType == "text")
-                {
-                    curPart = 0;
-                }
-                StringTokenizer tokens(std::string(pPayload), " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
-                if (tokens.count() == 4)
-                {
-                    int x, y, width, height;
-
-                    try {
-                        x = std::stoi(tokens[0]);
-                        y = std::stoi(tokens[1]);
-                        width = std::stoi(tokens[2]);
-                        height = std::stoi(tokens[3]);
-                    }
-                    catch (std::out_of_range&)
-                    {
-                        // something went wrong, invalidate everything
-                        Application::instance().logger().information(Util::logPrefix() + "Ignoring integer values out of range: " + pPayload);
-                        x = 0;
-                        y = 0;
-                        width = INT_MAX;
-                        height = INT_MAX;
-                    }
-
-                    srv->sendTextFrame("invalidatetiles:"
-                                       " part=" + std::to_string(curPart) +
-                                       " x=" + std::to_string(x) +
-                                       " y=" + std::to_string(y) +
-                                       " width=" + std::to_string(width) +
-                                       " height=" + std::to_string(height));
-                }
-                else
-                {
-                    srv->sendTextFrame("invalidatetiles: " + std::string(pPayload));
-                }
-            }
-            break;
-        case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR:
-            srv->sendTextFrame("invalidatecursor: " + std::string(pPayload));
-            break;
-        case LOK_CALLBACK_TEXT_SELECTION:
-            srv->sendTextFrame("textselection: " + std::string(pPayload));
-            break;
-        case LOK_CALLBACK_TEXT_SELECTION_START:
-            srv->sendTextFrame("textselectionstart: " + std::string(pPayload));
-            break;
-        case LOK_CALLBACK_TEXT_SELECTION_END:
-            srv->sendTextFrame("textselectionend: " + std::string(pPayload));
-            break;
-        case LOK_CALLBACK_CURSOR_VISIBLE:
-            srv->sendTextFrame("cursorvisible: " + std::string(pPayload));
-            break;
-        case LOK_CALLBACK_GRAPHIC_SELECTION:
-            srv->sendTextFrame("graphicselection: " + std::string(pPayload));
-            break;
-        case LOK_CALLBACK_CELL_CURSOR:
-            srv->sendTextFrame("cellcursor: " + std::string(pPayload));
-            break;
-        case LOK_CALLBACK_CELL_FORMULA:
-            srv->sendTextFrame("cellformula: " + std::string(pPayload));
-            break;
-        case LOK_CALLBACK_MOUSE_POINTER:
-            srv->sendTextFrame("mousepointer: " + std::string(pPayload));
-            break;
-        case LOK_CALLBACK_HYPERLINK_CLICKED:
-            srv->sendTextFrame("hyperlinkclicked: " + std::string(pPayload));
-            break;
-        case LOK_CALLBACK_STATE_CHANGED:
-            srv->sendTextFrame("statechanged: " + std::string(pPayload));
-            break;
-        case LOK_CALLBACK_STATUS_INDICATOR_START:
-            srv->sendTextFrame("statusindicatorstart:");
-            break;
-        case LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE:
-            srv->sendTextFrame("statusindicatorsetvalue: " + std::string(pPayload));
-            break;
-        case LOK_CALLBACK_STATUS_INDICATOR_FINISH:
-            srv->sendTextFrame("statusindicatorfinish:");
-            break;
-        case LOK_CALLBACK_SEARCH_NOT_FOUND:
-            srv->sendTextFrame("searchnotfound: " + std::string(pPayload));
-            break;
-        case LOK_CALLBACK_SEARCH_RESULT_SELECTION:
-            srv->sendTextFrame("searchresultselection: " + std::string(pPayload));
-            break;
-        case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED:
-            srv->getStatus("", 0);
-            srv->getPartPageRectangles("", 0);
-            break;
-        case LOK_CALLBACK_SET_PART:
-            srv->sendTextFrame("setpart: " + std::string(pPayload));
-            break;
-        case LOK_CALLBACK_UNO_COMMAND_RESULT:
-            srv->sendTextFrame("unocommandresult: " + std::string(pPayload));
-            break;
-        }
+        ChildProcessSession::_callbackQueue.enqueueNotification(new CallBackNotification(nType, pPayload ? pPayload : "(nil)", pData));
+        //std::string aPayLoad(pPayload ? pPayload : "(nil)");
     }
 }
 
+
 bool ChildProcessSession::loadDocument(const char *buffer, int length, StringTokenizer& tokens)
 {
     int part = -1;
diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp
index f20a8ddab..3c6917a9a 100644
--- a/loolwsd/LOOLKit.cpp
+++ b/loolwsd/LOOLKit.cpp
@@ -109,25 +109,38 @@ public:
     void callback(int nType, std::string& rPayload, void* pData)
     {
         ChildProcessSession *srv = reinterpret_cast<ChildProcessSession *>(pData);
-        pid_t tid = syscall(SYS_gettid);
 
-        //if ( nType == LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR )
-            std::cout << tid << " callback : " << srv->_viewId << " " << callbackTypeToString(nType) << " " << rPayload << std::endl;
-
-        switch ( nType )
+        switch ((LibreOfficeKitCallbackType) nType)
         {
         case LOK_CALLBACK_INVALIDATE_TILES:
             {
-                //int curPart = srv->_loKitDocument->pClass->getPart(srv->_loKitDocument);
-                int curPart = 0;
+                int curPart = srv->_loKitDocument->pClass->getPart(srv->_loKitDocument);
                 srv->sendTextFrame("curpart: part=" + std::to_string(curPart));
+                if (srv->_docType == "text")
+                {
+                    curPart = 0;
+                }
                 StringTokenizer tokens(rPayload, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
                 if (tokens.count() == 4)
                 {
-                    int x(std::stoi(tokens[0]));
-                    int y(std::stoi(tokens[1]));
-                    int width(std::stoi(tokens[2]));
-                    int height(std::stoi(tokens[3]));
+                    int x, y, width, height;
+
+                    try {
+                        x = std::stoi(tokens[0]);
+                        y = std::stoi(tokens[1]);
+                        width = std::stoi(tokens[2]);
+                        height = std::stoi(tokens[3]);
+                    }
+                    catch (std::out_of_range&)
+                    {
+                        // something went wrong, invalidate everything
+                        std::cout << Util::logPrefix() << "Ignoring integer values out of range: " << rPayload << std::endl;
+                        x = 0;
+                        y = 0;
+                        width = INT_MAX;
+                        height = INT_MAX;
+                    }
+
                     srv->sendTextFrame("invalidatetiles:"
                                        " part=" + std::to_string(curPart) +
                                        " x=" + std::to_string(x) +
@@ -135,22 +148,12 @@ public:
                                        " width=" + std::to_string(width) +
                                        " height=" + std::to_string(height));
                 }
-                else {
+                else
+                {
                     srv->sendTextFrame("invalidatetiles: " + rPayload);
                 }
             }
             break;
-        case LOK_CALLBACK_STATUS_INDICATOR_START:
-            srv->sendTextFrame("statusindicatorstart:");
-            break;
-
-        case LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE:
-            srv->sendTextFrame("statusindicatorsetvalue: " + rPayload);
-            break;
-
-        case LOK_CALLBACK_STATUS_INDICATOR_FINISH:
-            srv->sendTextFrame("statusindicatorfinish:");
-            break;
         case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR:
             srv->sendTextFrame("invalidatecursor: " + rPayload);
             break;
@@ -169,25 +172,49 @@ public:
         case LOK_CALLBACK_GRAPHIC_SELECTION:
             srv->sendTextFrame("graphicselection: " + rPayload);
             break;
+        case LOK_CALLBACK_CELL_CURSOR:
+            srv->sendTextFrame("cellcursor: " + rPayload);
+            break;
+        case LOK_CALLBACK_CELL_FORMULA:
+            srv->sendTextFrame("cellformula: " + rPayload);
+            break;
+        case LOK_CALLBACK_MOUSE_POINTER:
+            srv->sendTextFrame("mousepointer: " + rPayload);
+            break;
         case LOK_CALLBACK_HYPERLINK_CLICKED:
             srv->sendTextFrame("hyperlinkclicked: " + rPayload);
             break;
         case LOK_CALLBACK_STATE_CHANGED:
             srv->sendTextFrame("statechanged: " + rPayload);
             break;
+        case LOK_CALLBACK_STATUS_INDICATOR_START:
+            srv->sendTextFrame("statusindicatorstart:");
+            break;
+        case LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE:
+            srv->sendTextFrame("statusindicatorsetvalue: " + rPayload);
+            break;
+        case LOK_CALLBACK_STATUS_INDICATOR_FINISH:
+            srv->sendTextFrame("statusindicatorfinish:");
+            break;
         case LOK_CALLBACK_SEARCH_NOT_FOUND:
             srv->sendTextFrame("searchnotfound: " + rPayload);
             break;
+        case LOK_CALLBACK_SEARCH_RESULT_SELECTION:
+            srv->sendTextFrame("searchresultselection: " + rPayload);
+            break;
         case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED:
             srv->getStatus("", 0);
+            srv->getPartPageRectangles("", 0);
             break;
         case LOK_CALLBACK_SET_PART:
             srv->sendTextFrame("setpart: " + rPayload);
             break;
+        case LOK_CALLBACK_UNO_COMMAND_RESULT:
+            srv->sendTextFrame("unocommandresult: " + rPayload);
+            break;
         }
     }
 
-
     void run()
     {
         while ( true )
@@ -390,6 +417,13 @@ void run_lok_main(const std::string &loSubPath, Poco::UInt64 _childId, const std
         std::cout << Util::logPrefix() << "Cannot set thread name :" << strerror(errno) << std::endl;
 #endif
 
+    if (std::getenv("SLEEPFORDEBUGGER"))
+    {
+        std::cout << "Sleeping " << std::getenv("SLEEPFORDEBUGGER") << " seconds, attach process "
+                  << Process::id() << " in debugger now." << std::endl;
+        Thread::sleep(std::stoul(std::getenv("SLEEPFORDEBUGGER")) * 1000);
+    }
+
     try
     {
 #ifdef __APPLE__
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index 2bb61a18b..d543c324c 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -153,91 +153,6 @@ 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
@@ -752,7 +667,6 @@ std::string LOOLWSD::childRoot;
 std::string LOOLWSD::loSubPath = "lo";
 std::string LOOLWSD::jail;
 Poco::NamedMutex LOOLWSD::_namedMutexLOOL("loolwsd");
-Poco::SharedMemory LOOLWSD::_sharedForkChild("loolwsd", sizeof(bool), Poco::SharedMemory::AM_WRITE);
 
 int LOOLWSD::_numPreSpawnedChildren = 10;
 bool LOOLWSD::doTest = false;
@@ -916,299 +830,6 @@ void LOOLWSD::displayHelp()
     helpFormatter.format(std::cout);
 }
 
-// Writer, Impress or Calc
-void LOOLWSD::componentMain()
-{
-#ifdef __linux
-    if (prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("libreofficekit"), 0, 0, 0) != 0)
-        std::cout << Util::logPrefix() << "Cannot set thread name :" << strerror(errno) << std::endl;
-
-    setSignals(false);
-#endif
-
-    try
-    {
-        _namedMutexLOOL.lock();
-
-        Path jailPath = Path::forDirectory(LOOLWSD::childRoot + Path::separator() + std::to_string(_childId));
-        File(jailPath).createDirectory();
-
-        Path jailLOInstallation(jailPath, LOOLWSD::loSubPath);
-        jailLOInstallation.makeDirectory();
-        File(jailLOInstallation).createDirectory();
-
-        // Copy (link) LO installation and other necessary files into it from the template
-
-        linkOrCopy(LOOLWSD::sysTemplate, jailPath);
-        linkOrCopy(LOOLWSD::loTemplate, jailLOInstallation);
-
-        // 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(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)
-        {
-            Application::instance().logger().error(Util::logPrefix() +
-                    "mknod(" + jailPath.toString() + "/dev/random) failed: " +
-                    strerror(errno));
-
-        }
-        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)
-        {
-            Application::instance().logger().error(Util::logPrefix() +
-                    "mknod(" + jailPath.toString() + "/dev/urandom) failed: " +
-                    strerror(errno));
-        }
-#endif
-
-        Application::instance().logger().information("componentMain -> chroot(\"" + jailPath.toString() + "\")");
-        if (chroot(jailPath.toString().c_str()) == -1)
-        {
-            logger().error("chroot(\"" + jailPath.toString() + "\") failed: " + strerror(errno));
-            exit(Application::EXIT_UNAVAILABLE);
-        }
-
-        if (chdir("/") == -1)
-        {
-            logger().error(std::string("chdir(\"/\") in jail failed: ") + strerror(errno));
-            exit(Application::EXIT_UNAVAILABLE);
-        }
-
-#ifdef __linux
-        dropCapability(CAP_SYS_CHROOT);
-        dropCapability(CAP_MKNOD);
-        dropCapability(CAP_FOWNER);
-#else
-        dropCapability();
-#endif
-
-        if (std::getenv("SLEEPFORDEBUGGER"))
-        {
-            std::cout << "Sleeping " << std::getenv("SLEEPFORDEBUGGER") << " seconds, " <<
-                "attach process " << Process::id() << " in debugger now." << std::endl;
-            Thread::sleep(std::stoul(std::getenv("SLEEPFORDEBUGGER")) * 1000);
-        }
-
-#ifdef __APPLE__
-        LibreOfficeKit *loKit(lok_init_2(("/" + loSubPath + "/Frameworks").c_str(), "file:///user"));
-#else
-        LibreOfficeKit *loKit(lok_init_2(("/" + loSubPath + "/program").c_str(), "file:///user"));
-#endif
-
-        if (!loKit)
-        {
-            logger().fatal(Util::logPrefix() + "LibreOfficeKit initialisation failed");
-            exit(Application::EXIT_UNAVAILABLE);
-        }
-
-        _namedMutexLOOL.unlock();
-
-        // Open websocket connection between the child process and the
-        // parent. The parent forwards us requests that it can't handle.
-
-        HTTPClientSession cs("127.0.0.1", MASTER_PORT_NUMBER);
-        cs.setTimeout(0);
-        HTTPRequest request(HTTPRequest::HTTP_GET, LOOLWSD::CHILD_URI);
-        HTTPResponse response;
-        std::shared_ptr<WebSocket> ws(new WebSocket(cs, request, response));
-
-        std::shared_ptr<ChildProcessSession> session(new ChildProcessSession(ws, loKit, nullptr, std::to_string(_childId)));
-
-        ws->setReceiveTimeout(0);
-
-        std::string hello("child " + std::to_string(_childId) + " " + std::to_string(Process::id()));
-        session->sendTextFrame(hello);
-
-        TileQueue queue;
-        Thread queueHandlerThread;
-        QueueHandler handler(queue);
-
-        handler.setSession(session);
-        queueHandlerThread.start(handler);
-
-        int flags;
-        int n;
-        do
-        {
-            char buffer[1024];
-            n = ws->receiveFrame(buffer, sizeof(buffer), flags);
-
-            if (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE)
-            {
-                std::string firstLine = getFirstLine(buffer, n);
-                StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
-
-                // The only kind of messages a child process receives are the single-line ones (?)
-                assert(firstLine.size() == static_cast<std::string::size_type>(n));
-
-                queue.put(firstLine);
-            }
-        }
-        while (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE);
-
-        queue.clear();
-        queue.put("eof");
-        queueHandlerThread.join();
-
-        // Destroy lokit document
-        if (session->_loKitDocument)
-            session->_loKitDocument->pClass->destroy(session->_loKitDocument);
-
-        // Destroy LibreOfficeKit
-        loKit->pClass->destroy(loKit);
-
-        // wait to finish lo_startmain thread
-        pthread_exit(0);
-    }
-    catch (Exception& exc)
-    {
-        logger().log(Util::logPrefix() + "Exception: " + exc.what());
-    }
-    catch (std::exception& exc)
-    {
-        logger().error(Util::logPrefix() + "Exception: " + exc.what());
-    }
-
-    exit(Application::EXIT_OK);
-}
-
-int LOOLWSD::createComponent()
-{
-    int pid;
-
-    _childId = Util::rng::getNext();
-
-    if ((pid = fork()) == -1)
-    {
-        std::cout << "Fork failed." << std::endl;
-        return Application::EXIT_UNAVAILABLE;
-    }
-
-    if (!pid)
-    {
-        componentMain();
-    }
-
-    MasterProcessSession::_childProcesses[pid] = _childId;
-
-    return Application::EXIT_OK;
-}
-
-void LOOLWSD::startupComponent(int nComponents)
-{
-    for (int nCntr = nComponents; nCntr; nCntr--)
-    {
-        if (createComponent() < 0)
-            break;
-    }
-}
-
-void LOOLWSD::desktopMain()
-{
-#ifdef __linux
-    if (prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("loolbroker"), 0, 0, 0) != 0)
-        std::cout << Util::logPrefix() << "Cannot set thread name :" << strerror(errno) << std::endl;
-
-    setSignals(false);
-#endif
-
-    startupComponent(_numPreSpawnedChildren);
-
-    while (MasterProcessSession::_childProcesses.size() > 0)
-    {
-        int status;
-        pid_t pid = waitpid(-1, &status, WUNTRACED | WNOHANG);
-        if (pid > 0)
-        {
-            if ( MasterProcessSession::_childProcesses.find(pid) != MasterProcessSession::_childProcesses.end() )
-            {
-                if ((WIFEXITED(status) || WIFSIGNALED(status) || WTERMSIG(status) ) )
-                {
-                    std::cout << Util::logPrefix() << "One of our known child processes died :" << std::to_string(pid)  << std::endl;
-                    // remove chroot child
-                    File aWorkSpace(LOOLWSD::childRoot + Path::separator() +
-                                    std::to_string(MasterProcessSession::_childProcesses[pid]));
-                    if (aWorkSpace.exists())
-                        aWorkSpace.remove(true);
-
-                    MasterProcessSession::_childProcesses.erase(pid);
-                }
-
-                if ( WCOREDUMP(status) )
-                    std::cout << Util::logPrefix() << "The child process [" << pid << "] produced a core dump." << std::endl;
-
-                if ( WIFSTOPPED(status) )
-                    std::cout << Util::logPrefix() << "The child process was stopped by delivery of a signal." << std::endl;
-
-                if ( WSTOPSIG(status) )
-                    std::cout << Util::logPrefix() << "The child process was stopped." << std::endl;
-
-                if ( WIFCONTINUED(status) )
-                    std::cout << Util::logPrefix() << "The child process was resumed." << std::endl;
-            }
-            else
-            {
-                std::cout << Util::logPrefix() << "None of our known child processes died :" << std::to_string(pid)  << std::endl;
-            }
-        }
-        else if (pid < 0)
-            std::cout << Util::logPrefix() << "Child error: " << strerror(errno);
-
-        if (!LOOLWSD::isShutDown && _sharedForkChild.begin()[0] > 0 )
-        {
-            _namedMutexLOOL.lock();
-            _sharedForkChild.begin()[0] = _sharedForkChild.begin()[0] - 1;
-            std::cout << Util::logPrefix() << "Create child session, fork new one" << std::endl;
-            _namedMutexLOOL.unlock();
-            if (createComponent() < 0 )
-                break;
-        }
-
-        ++timeoutCounter;
-        if (timeoutCounter == INTERVAL_PROBES)
-        {
-            timeoutCounter = 0;
-            sleep(MAINTENANCE_INTERVAL);
-        }
-    }
-
-    exit(Application::EXIT_OK);
-}
-
-
-int LOOLWSD::createDesktop()
-{
-    int pid;
-
-    if ((pid = fork()) == -1)
-    {
-        std::cout << "createDesktop fork failed." << std::endl;
-        return Application::EXIT_UNAVAILABLE;
-    }
-
-    if (!pid)
-    {
-        desktopMain();
-    }
-
-    MasterProcessSession::_childProcesses[pid] = pid;
-
-    return Application::EXIT_OK;
-}
-
 int LOOLWSD::createBroker()
 {
     Process::Args args;
diff --git a/loolwsd/LOOLWSD.hpp b/loolwsd/LOOLWSD.hpp
index 3f7cfee4e..e14b0e46f 100644
--- a/loolwsd/LOOLWSD.hpp
+++ b/loolwsd/LOOLWSD.hpp
@@ -42,7 +42,6 @@ public:
     static std::string childRoot;
     static std::string loSubPath;
     static std::string jail;
-    static Poco::SharedMemory _sharedForkChild;
     static Poco::NamedMutex _namedMutexLOOL;
     static Poco::UInt64 _childId;
 
commit 80e7bcd4ea08e218e3190ef6d22e92e92e94b29a
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Sun Dec 20 12:59:26 2015 -0500
Commit:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Mon Dec 21 11:18:43 2015 -0500

    loolwsd: Nominal logger and fixes
    
    Nominal logging interface and a fix to using Poco
    Application from LOOLKit, which is not a Poco App,
    which caused core dump.
    
    Logs now include process name.
    Added logs to strategic places and some cleanups.
    
    Change-Id: Ib7dcc4f1033dddf7c87cd2e786a91f5b482fb312

diff --git a/loolwsd/ChildProcessSession.cpp b/loolwsd/ChildProcessSession.cpp
index b74138ba0..dd56da0a5 100644
--- a/loolwsd/ChildProcessSession.cpp
+++ b/loolwsd/ChildProcessSession.cpp
@@ -18,7 +18,6 @@
 #include <Poco/String.h>
 #include <Poco/StringTokenizer.h>
 #include <Poco/URI.h>
-#include <Poco/Util/Application.h>
 
 #include "ChildProcessSession.hpp"
 #include "LOKitHelper.hpp"
@@ -38,7 +37,6 @@ using Poco::Process;
 using Poco::ProcessHandle;
 using Poco::StringTokenizer;
 using Poco::URI;
-using Poco::Util::Application;
 
 Poco::NotificationQueue ChildProcessSession::_callbackQueue;
 Poco::Mutex ChildProcessSession::_mutex;
@@ -67,11 +65,11 @@ ChildProcessSession::~ChildProcessSession()
 
 bool ChildProcessSession::handleInput(const char *buffer, int length)
 {
+    Log::info(_kindString + ",Input," + getAbbreviatedMessage(buffer, length));
+
     std::string firstLine = getFirstLine(buffer, length);
     StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
 
-    Application::instance().logger().information(Util::logPrefix() + _kindString + ",Input," + getAbbreviatedMessage(buffer, length));
-
     if (tokens[0] == "canceltiles")
     {
         // this command makes sense only on the command queue level, nothing
@@ -363,7 +361,7 @@ bool ChildProcessSession::loadDocument(const char *buffer, int length, StringTok
     if ((_loKitDocument = _loKit->pClass->documentLoad(_loKit, aUri.toString().c_str())) == NULL)
     {
         sendTextFrame("error: cmd=load kind=failed");
-        Application::instance().logger().information(Util::logPrefix() + "Failed to load: " + aUri.toString() + ", error is: " + _loKit->pClass->getError(_loKit));
+        Log::error("Failed to load: " + aUri.toString() + ", error is: " + _loKit->pClass->getError(_loKit));
         return false;
     }
 
@@ -435,7 +433,7 @@ bool ChildProcessSession::getStatus(const char* /*buffer*/, int /*length*/)
     StringTokenizer tokens(status, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
     if (!getTokenString(tokens[1], "type", _docType))
     {
-        Application::instance().logger().information(Util::logPrefix() + "failed to get document type from" + status);
+        Log::error("failed to get document type from" + status);
     }
     sendTextFrame(status);
 
diff --git a/loolwsd/LOOLBroker.cpp b/loolwsd/LOOLBroker.cpp
index 5a64598bc..cca628e23 100644
--- a/loolwsd/LOOLBroker.cpp
+++ b/loolwsd/LOOLBroker.cpp
@@ -233,7 +233,7 @@ namespace
             }
             if (setuid(LOOLWSD::uid) != 0)
             {
-                Application::instance().logger().error(std::string("setuid() failed: ") + strerror(errno));
+                Log::error(std::string("setuid() failed: ") + strerror(errno));
             }
         }
 #endif
@@ -368,7 +368,6 @@ public:
     {
         Process::PID nPID;
 
-        //std::cout << Util::logPrefix() << "Broker,Input," <<  aMessage << std::endl;
         StringTokenizer tokens(aMessage, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
         if (tokens[0] == "request" && tokens.count() == 3)
         {
@@ -469,6 +468,7 @@ public:
                     }
                     pStart = aBuffer;
                     pEnd   = aBuffer + nBytes;
+                    std::cout << Util::logPrefix() << "Broker readFIFO [" << std::string(pStart, nBytes) << "]" << std::endl;
                 }
             }
 
@@ -565,6 +565,7 @@ static int createLibreOfficeKit(bool sharePages, std::string loSubPath, Poco::UI
 
         ProcessHandle procChild = Process::launch(executable, args);
         child = procChild.id();
+        std::cout << Util::logPrefix() << "Launched kit process: " << child << std::endl;
 
         if ( ( nFIFOWriter = open(pipe.c_str(), O_WRONLY) ) < 0 )
         {
@@ -582,7 +583,9 @@ static int startupLibreOfficeKit(bool sharePages, int nLOKits,
 {
     Process::PID pId = -1;
 
-    std::cout << Util::logPrefix() << "starting " << nLOKits << " LoKit instaces." << std::endl;
+    std::cout << Util::logPrefix() << "starting " << nLOKits << " LoKit instaces."
+              << " Shared: " << sharePages << ", loSubPath: " << loSubPath
+              << ", child: " << child << std::endl;
     for (int nCntr = nLOKits; nCntr; nCntr--)
     {
         if ( (pId = createLibreOfficeKit(sharePages, loSubPath, child)) < 0)
@@ -592,7 +595,7 @@ static int startupLibreOfficeKit(bool sharePages, int nLOKits,
         }
     }
 
-   return pId;
+    return pId;
 }
 
 // Broker process
@@ -605,6 +608,8 @@ int main(int argc, char** argv)
     std::string loTemplate;
     int _numPreSpawnedChildren = 0;
 
+    Log::initialize("brk");
+
     for (int i = 0; i < argc; ++i)
     {
         char *cmd = argv[i];
@@ -635,9 +640,7 @@ int main(int argc, char** argv)
         }
         else if (strstr(cmd, "--numprespawns=") == cmd)
         {
-            std::cout << "CMD: " << cmd << std::endl;
             eq = strchrnul(cmd, '=');
-            std::cout << "EQ: " << std::string(eq + 1) << std::endl;
             if (*eq)
                 _numPreSpawnedChildren = std::stoi(std::string(++eq));
         }
@@ -697,8 +700,6 @@ int main(int argc, char** argv)
         std::cout << Util::logPrefix() << aError.what() << std::endl;
     }
 
-    std::cout << "In Broker!" << std::endl;
-
     const Poco::UInt64 _childId = Util::rng::getNext();
 
     Path jailPath = Path::forDirectory(childRoot + Path::separator() + std::to_string(_childId));
diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp
index af0b5f6f2..f20a8ddab 100644
--- a/loolwsd/LOOLKit.cpp
+++ b/loolwsd/LOOLKit.cpp
@@ -14,11 +14,11 @@
 #include <sys/prctl.h>
 #include <sys/poll.h>
 #include <sys/syscall.h>
+#include <signal.h>
 
 #include <memory>
 #include <iostream>
 
-#include <Poco/Util/Application.h>
 #include <Poco/Net/WebSocket.h>
 #include <Poco/Net/HTTPClientSession.h>
 #include <Poco/Net/HTTPRequest.h>
@@ -232,15 +232,28 @@ public:
     {
 #ifdef __linux
       if (prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("queue_handler"), 0, 0, 0) != 0)
-        std::cout << Util::logPrefix() << "Cannot set thread name :" << strerror(errno) << std::endl;
+        Log::error(std::string("Cannot set thread name :") + strerror(errno));
 #endif
-        while (true)
+        try
         {
-            std::string input = _queue.get();
-            if (input == "eof")
-                break;
-            if (!_session->handleInput(input.c_str(), input.size()))
-                break;
+            while (true)
+            {
+                std::string input = _queue.get();
+                if (input == "eof")
+                    break;
+                if (!_session->handleInput(input.c_str(), input.size()))
+                    break;
+            }
+        }
+        catch(std::exception& ex)
+        {
+            Log::error(std::string("Exception: ") + ex.what());
+            raise(SIGABRT);
+        }
+        catch(...)
+        {
+            Log::error("Unknown Exception.");
+            raise(SIGABRT);
         }
     }
 
@@ -258,6 +271,7 @@ public:
         _childId(childId),
         _threadId(threadId)
     {
+        std::cout << Util::logPrefix() << "New connection in child: " << _childId << ", thread: " << _threadId << std::endl;
     }
 
     void start()
@@ -332,7 +346,6 @@ public:
             queue.put("eof");
             queueHandlerThread.join();
         }
-
         catch (Exception& exc)
         {
             std::cout << Util::logPrefix() + "Exception: " + exc.what() << std::endl;
@@ -345,6 +358,7 @@ public:
 
     ~Connection()
     {
+        std::cout << Util::logPrefix() << "Closing connection in child: " << _childId << ", thread: " << _threadId << std::endl;
         //_thread.stop();
     }
 
@@ -449,7 +463,6 @@ void run_lok_main(const std::string &loSubPath, Poco::UInt64 _childId, const std
                 if ( aChar == '\r' && *pStart == '\n')
                 {
                     pStart++;
-                    //std::cout << Util::logPrefix() << "child receive: " << aMessage << std::endl;
                     StringTokenizer tokens(aMessage, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
 
                     if (tokens[0] == "search")
@@ -520,10 +533,11 @@ void run_lok_main(const std::string &loSubPath, Poco::UInt64 _childId, const std
             }
         }
 
-
         // Destroy LibreOfficeKit
         loKit->pClass->destroy(loKit);
 
+        std::cout << Util::logPrefix() << "loolkit finished OK!" << std::endl;
+
         pthread_exit(0);
     }
     catch (Exception& exc)
@@ -534,8 +548,6 @@ void run_lok_main(const std::string &loSubPath, Poco::UInt64 _childId, const std
     {
         std::cout << Util::logPrefix() + "Exception: " + exc.what() << std::endl;
     }
-
-    std::cout << Util::logPrefix() << "loolkit finished OK!" << std::endl;
 }
 
 #ifndef LOOLKIT_NO_MAIN
@@ -547,6 +559,8 @@ int main(int argc, char** argv)
     Poco::UInt64 _childId = 0;
     std::string _pipe;
 
+    Log::initialize("kit");
+
     for (int i = 1; i < argc; ++i)
     {
         char *cmd = argv[i];
diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp
index db59e7680..b43908c5d 100644
--- a/loolwsd/LOOLSession.cpp
+++ b/loolwsd/LOOLSession.cpp
@@ -44,7 +44,6 @@
 #include <Poco/ThreadLocal.h>
 #include <Poco/URI.h>
 #include <Poco/URIStreamOpener.h>
-#include <Poco/Util/Application.h>
 #include <Poco/Exception.h>
 #include <Poco/Net/NetException.h>
 #include <Poco/Net/DialogSocket.h>
@@ -77,7 +76,6 @@ using Poco::ThreadLocal;
 using Poco::UInt64;
 using Poco::URI;
 using Poco::URIStreamOpener;
-using Poco::Util::Application;
 using Poco::Exception;
 using Poco::Net::DialogSocket;
 using Poco::Net::SocketAddress;
@@ -107,13 +105,18 @@ LOOLSession::LOOLSession(std::shared_ptr<WebSocket> ws, Kind kind) :
 
 LOOLSession::~LOOLSession()
 {
-    std::cout << Util::logPrefix() << "LOOLSession dtor this=" << this << " " << _kind << std::endl;
+    std::cout << Util::logPrefix() << "loolsession dtor this=" << this << " " << _kind << std::endl;
     if (_ws)
         Util::shutdownWebSocket(*_ws);
 }
 
 void LOOLSession::sendTextFrame(const std::string& text)
 {
+    if (!_ws)
+        Log::error("No socket to send to.");
+    else
+        Log::debug(_kindString + ",Send," + getAbbreviatedMessage(text.c_str(), text.size()));
+
     std::unique_lock<std::mutex> lock(_mutex);
 
     _ws->sendFrame(text.data(), text.size());
@@ -121,6 +124,11 @@ void LOOLSession::sendTextFrame(const std::string& text)
 
 void LOOLSession::sendBinaryFrame(const char *buffer, int length)
 {
+    if (!_ws)
+        Log::error("No socket to send to.");
+    else
+        Log::debug(_kindString + ",Send," + std::to_string(length) + " bytes");
+
     std::unique_lock<std::mutex> lock(_mutex);
 
     if (length > 1000)
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index 41da9bbde..2bb61a18b 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -251,25 +251,25 @@ namespace
         caps = cap_get_proc();
         if (caps == NULL)
         {
-            Application::instance().logger().error(Util::logPrefix() + "cap_get_proc() failed: " + strerror(errno));
+            Log::error(std::string("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));
+            Log::error(std::string("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));
+            Log::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);
+        Log::info(std::string("Capabilities now: ") + capText);
         cap_free(capText);
 
         cap_free(caps);
@@ -283,7 +283,7 @@ namespace
             // to do chroot().
             if (setuid(getuid()) != 0)
             {
-                Application::instance().logger().error(std::string("setuid() failed: ") + strerror(errno));
+                Log::error(std::string("setuid() failed: ") + strerror(errno));
             }
         }
 #if ENABLE_DEBUG
@@ -307,7 +307,7 @@ namespace
             }
             if (setuid(LOOLWSD::uid) != 0)
             {
-                Application::instance().logger().error(std::string("setuid() failed: ") + strerror(errno));
+                Log::error(std::string("setuid() failed: ") + strerror(errno));
             }
         }
 #endif
@@ -608,7 +608,7 @@ public:
             }
             catch (WebSocketException& exc)
             {
-                Application::instance().logger().error(Util::logPrefix() + "RequestHandler::handleRequest(), WebSocketException: " + exc.message());
+                Log::error("RequestHandler::handleRequest(), WebSocketException: " + exc.message());
                 switch (exc.code())
                 {
                 case WebSocket::WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION:
@@ -626,7 +626,7 @@ public:
         }
         catch (IOException& exc)
         {
-            Application::instance().logger().error(Util::logPrefix() + "IOException: " + exc.message());
+            Log::error("IOException: " + exc.message());
         }
     }
 };
@@ -651,7 +651,7 @@ public:
             line += " / " + it->first + ": " + it->second;
         }
 
-        Application::instance().logger().information(line);
+        Log::info(line);
         return new RequestHandler();
     }
 };
@@ -688,7 +688,7 @@ public:
         }
         catch (WebSocketException& exc)
         {
-            Application::instance().logger().error(Util::logPrefix() + "TestOutput::run(), WebSocketException: " + exc.message());
+            Log::error("TestOutput::run(), WebSocketException: " + exc.message());
             _ws.close();
         }
     }
@@ -1223,7 +1223,7 @@ int LOOLWSD::createBroker()
 
     const auto msg = Util::logPrefix() + "Launching broker: " + executable + " "
                    + Poco::cat(std::string(" "), args.begin(), args.end());
-    Application::instance().logger().information(msg);
+    Log::info(msg);
 
     ProcessHandle child = Process::launch(executable, args);
 
@@ -1255,6 +1255,8 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
     setSignals(false);
 #endif
 
+    Log::initialize("brk");
+
     if (access(cache.c_str(), R_OK | W_OK | X_OK) != 0)
     {
         std::cout << Util::logPrefix() << "Unable to access " << cache <<
@@ -1394,14 +1396,14 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
     // Terminate child processes
     for (auto i : MasterProcessSession::_childProcesses)
     {
-        logger().information(Util::logPrefix() + "Requesting child process " + std::to_string(i.first) + " to terminate");
+        Log::info("Requesting child process " + std::to_string(i.first) + " to terminate");
         Process::requestTermination(i.first);
     }
 
     // wait broker process finish
     waitpid(-1, &status, WUNTRACED);
 
-    std::cout << Util::logPrefix() << "loolwsd finished OK!" << std::endl;
+    Log::info("loolwsd finished OK!");
     return Application::EXIT_OK;
 }
 
diff --git a/loolwsd/MasterProcessSession.cpp b/loolwsd/MasterProcessSession.cpp
index 513e20021..2428b821e 100644
--- a/loolwsd/MasterProcessSession.cpp
+++ b/loolwsd/MasterProcessSession.cpp
@@ -16,7 +16,6 @@
 #include <Poco/Random.h>
 #include <Poco/URI.h>
 #include <Poco/URIStreamOpener.h>
-#include <Poco/Util/Application.h>
 
 #include "LOOLProtocol.hpp"
 #include "LOOLSession.hpp"
@@ -42,7 +41,6 @@ using Poco::StringTokenizer;
 using Poco::Thread;
 using Poco::UInt64;
 using Poco::URI;
-using Poco::Util::Application;
 
 std::map<Process::PID, UInt64> MasterProcessSession::_childProcesses;
 
@@ -73,7 +71,7 @@ MasterProcessSession::~MasterProcessSession()
 
 bool MasterProcessSession::handleInput(const char *buffer, int length)
 {
-    Application::instance().logger().information(Util::logPrefix() + _kindString + ",Input," + getAbbreviatedMessage(buffer, length));
+    Log::info(_kindString + ",Recv," + getAbbreviatedMessage(buffer, length));
 
     std::string firstLine = getFirstLine(buffer, length);
     StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
@@ -609,7 +607,7 @@ void MasterProcessSession::dispatchChild()
         }
         catch (Exception& exc)
         {
-            Application::instance().logger().error( Util::logPrefix() +
+            Log::error(
                 "createDirectories(\"" + aDstPath.toString() + "\") failed: " + exc.displayText() );
 
         }
@@ -620,11 +618,11 @@ void MasterProcessSession::dispatchChild()
             aToCleanup.remove();
 
 #ifdef __linux
-        Application::instance().logger().information(Util::logPrefix() + "Linking " + aSrcFile.toString() + " to " + aDstFile.toString());
+        Log::info("Linking " + aSrcFile.toString() + " to " + aDstFile.toString());
         if (!File(aDstFile).exists() && link(aSrcFile.toString().c_str(), aDstFile.toString().c_str()) == -1)
         {
             // Failed
-            Application::instance().logger().error( Util::logPrefix() +
+            Log::error(
                 "link(\"" + aSrcFile.toString() + "\",\"" + aDstFile.toString() + "\") failed: " + strerror(errno) );
         }
 #endif
@@ -634,13 +632,13 @@ void MasterProcessSession::dispatchChild()
             //fallback
             if (!File(aDstFile).exists())
             {
-                Application::instance().logger().information(Util::logPrefix() + "Copying " + aSrcFile.toString() + " to " + aDstFile.toString());
+                Log::info(Util::logPrefix() + "Copying " + aSrcFile.toString() + " to " + aDstFile.toString());
                 File(aSrcFile).copyTo(aDstFile.toString());
             }
         }
         catch (Exception& exc)
         {
-            Application::instance().logger().error( Util::logPrefix() +
+            Log::error(
                 "copyTo(\"" + aSrcFile.toString() + "\",\"" + aDstFile.toString() + "\") failed: " + exc.displayText());
         }
     }
@@ -654,10 +652,13 @@ void MasterProcessSession::dispatchChild()
 
 void MasterProcessSession::forwardToPeer(const char *buffer, int length)
 {
-    Application::instance().logger().information(Util::logPrefix() + _kindString + ",forwardToPeer," + getAbbreviatedMessage(buffer, length));
+    Log::info(_kindString + ",forwardToPeer," + getAbbreviatedMessage(buffer, length));
     auto peer = _peer.lock();
     if (!peer)
+    {
+        Log::error("no peer to forward to");
         return;
+    }
     peer->sendBinaryFrame(buffer, length);
 }
 
diff --git a/loolwsd/TileCache.cpp b/loolwsd/TileCache.cpp
index 3bd593916..56641c116 100644
--- a/loolwsd/TileCache.cpp
+++ b/loolwsd/TileCache.cpp
@@ -27,7 +27,6 @@
 #include <Poco/StringTokenizer.h>
 #include <Poco/Timestamp.h>
 #include <Poco/URI.h>
-#include <Poco/Util/Application.h>
 
 #include "LOOLWSD.hpp"
 #include "LOOLProtocol.hpp"
@@ -42,7 +41,6 @@ using Poco::StringTokenizer;
 using Poco::SyntaxException;
 using Poco::Timestamp;
 using Poco::URI;
-using Poco::Util::Application;
 
 using namespace LOOLProtocol;
 
@@ -384,7 +382,7 @@ void TileCache::setup(const std::string& timestamp)
         Timestamp::TimeVal lastTimeVal;
         std::istringstream(timestamp) >> lastTimeVal;
         lastModified = lastTimeVal;
-        Application::instance().logger().information(Util::logPrefix() + "Timestamp provided externally: " + timestamp);
+        Log::info("Timestamp provided externally: " + timestamp);
 
         cleanEverything = (getLastModified() < Timestamp(lastModified));
     }
@@ -401,7 +399,7 @@ void TileCache::setup(const std::string& timestamp)
         {
             // document changed externally, clean up everything
             cacheDir.remove(true);
-            Application::instance().logger().information(Util::logPrefix() + "Completely cleared cache: " + toplevelCacheDirName());
+            Log::info("Completely cleared cache: " + toplevelCacheDirName());
         }
         else
         {
@@ -410,7 +408,7 @@ void TileCache::setup(const std::string& timestamp)
             if (editingCacheDir.exists())
             {
                 editingCacheDir.remove(true);
-                Application::instance().logger().information(Util::logPrefix() + "Cleared the editing cache: " + cacheDirName(true));
+                Log::info("Cleared the editing cache: " + cacheDirName(true));
             }
         }
     }
diff --git a/loolwsd/Util.cpp b/loolwsd/Util.cpp
index 4ce1cd00b..87dd14a63 100644
--- a/loolwsd/Util.cpp
+++ b/loolwsd/Util.cpp
@@ -69,6 +69,38 @@ namespace rng
 }
 }
 
+namespace Log
+{
+    static std::string binname;
+
+    void initialize(const std::string& name)
+    {
+        binname = name;
+        auto& logger = Poco::Logger::get(name);
+        logger.information("Initializing " + name);
+    }
+
+    Poco::Logger& logger()
+    {
+        return Poco::Logger::get(binname);
+    }
+
+    void debug(const std::string& msg)
+    {
+        return logger().debug(Util::logPrefix() + msg);
+    }
+
+    void info(const std::string& msg)
+    {
+        logger().information(Util::logPrefix() + msg);
+    }
+
+    void error(const std::string& msg)
+    {
+        return logger().error(Util::logPrefix() + msg);
+    }
+}
+
 namespace Util
 {
     static const Poco::Int64 epochStart = Poco::Timestamp().epochMicroseconds();
@@ -86,8 +118,10 @@ namespace Util
         usec %= (one_s);
 
         std::ostringstream stream;
-        stream << Poco::Process::id() << "," << std::setw(2) << std::setfill('0') << (Poco::Thread::current() ? Poco::Thread::current()->id() : 0) << "," <<
-            std::setw(2) << hours << ":" << std::setw(2) << minutes << ":" << std::setw(2) << seconds << "." << std::setw(6) << usec << ",";
+        stream << Log::binname << ',' << Poco::Process::id() << ',' << std::setw(2) << std::setfill('0')
+               << (Poco::Thread::current() ? Poco::Thread::current()->id() : 0) << ',' << std::setw(2) << ','
+               << hours << ':' << std::setw(2) << minutes << ':' << std::setw(2) << seconds << "." << std::setw(6) << usec
+               << ',';
 
         return stream.str();
     }
diff --git a/loolwsd/Util.hpp b/loolwsd/Util.hpp
index 8db7df38a..8b1babfe7 100644
--- a/loolwsd/Util.hpp
+++ b/loolwsd/Util.hpp
@@ -13,6 +13,7 @@
 #include <string>
 
 #include <Poco/Net/WebSocket.h>
+#include <Poco/Logger.h>
 
 #define LOK_USE_UNSTABLE_API
 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
@@ -44,6 +45,17 @@ namespace Util
     ssize_t readMessage(int nPipe, char* pBuffer, ssize_t nSize);
 };
 
+//TODO: Move to own file.
+namespace Log
+{
+    void initialize(const std::string& name);
+    Poco::Logger& logger();
+
+    void debug(const std::string& msg);
+    void info(const std::string& msg);
+    void error(const std::string& msg);
+}
+
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit d99d4376ff9e1052543bf850caf5734894ef393a
Author:     Henry Castro <hcastro at collabora.com>
AuthorDate: Sun Dec 20 12:45:19 2015 -0500
Commit:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Mon Dec 21 11:18:43 2015 -0500

    loolwsd: merged systemplate-setup
    
    Change-Id: Id066b02e405246d6a0a268aa1b29e09cd7730642

diff --git a/loolwsd/loolwsd-systemplate-setup b/loolwsd/loolwsd-systemplate-setup
index 627f23040..c2f4483ae 100755
--- a/loolwsd/loolwsd-systemplate-setup
+++ b/loolwsd/loolwsd-systemplate-setup
@@ -6,6 +6,7 @@ test $# -eq 2 || { echo "Usage: $0 <chroot template directory for system libs to
 
 CHROOT=$1
 INSTDIR=$2
+POCODIR=/usr/local/lib
 
 test -d "$INSTDIR" || { echo "No such directory: $INSTDIR"; exit 1; }
 
@@ -45,6 +46,9 @@ cd / || exit 1
 	     lib/*-linux-gnu/libnss* \
 		 -type l
 
+	find lib/libnss_* lib64/libnss_* -type l
+	find lib/*-linux-gnu/libnss* -type l
+
 	# Go through the LO shared objects and check what system libraries
 	# they link to.
 	find $INSTDIR -name '*.so' -o -name '*.so.[0-9]*' |
@@ -52,6 +56,14 @@ cd / || exit 1
 	    ldd $file 2>/dev/null
 	done |
 	grep -v dynamic | cut -d " " -f 3 | grep -E '^(/lib|/usr)' | sort -u | sed -e 's,^/,,'
+
+	# Go through the loolkit
+	find $POCODIR -name '*Poco*.so' -o -name '*.so.[0-9]*' |
+	while read file; do
+	    ldd $file 2>/dev/null
+	done |
+	grep -v dynamic | cut -d " " -f 3 | grep -E '^(/lib|/usr)' | sort -u | sed -e 's,^/,,'
+
     else
 	find usr/lib/dyld  \
 	     usr/lib/*.dylib \
@@ -92,6 +104,67 @@ cd / || exit 1
 cpio -p -d -L $CHROOT
 
 mkdir -p $CHROOT/tmp
+mkdir -p $CHROOT/usr/bin/
+dummy=$CHROOT/usr/bin/dummy
+
+# checking for library containing Poco::Application
+cat <<_ACEOF >$dummy.cpp
+#include <iostream>
+#include <Poco/Util/Application.h>
+
+using Poco::Util::Application;
+
+int main ()
+{
+  std::cout << "Poco functionality OK!" << std::endl;
+  return Application::EXIT_OK;
+}
+_ACEOF
+
+gcc_compile='g++ -o $dummy.o -c $dummy.cpp'
+(eval "$gcc_compile") 2>$dummy.err
+
+if ! test $? = 0; then
+  cat $dummy.err;
+  exit 1;
+fi
+
+gcc_link='g++ -o $dummy -lcap -lpng -ldl  -lPocoNet -lPocoUtil -lPocoXML -lPocoJSON -lPocoFoundation $dummy.o'
+(eval "$gcc_link") 2>$dummy.err
+
+if ! test $? = 0; then
+  cat $dummy.err;
+  exit 1;
+fi
+
+lib_poco=$( echo "$dummy" |
+  while read file; do
+    ldd $file 2>/dev/null
+  done |
+  grep -v dynamic | cut -d " " -f 3 | grep -E '^(/lib|/usr)')
+
+for lib in $lib_poco
+do
+  cp --parent -n $lib $CHROOT
+
+  libs=$( echo $lib |
+  while read file; do
+    ldd $file 2>/dev/null
+  done |
+  grep -v dynamic | cut -d " " -f 3 | grep -E '^(/lib|/usr)')
+
+  for sofile in $libs
+  do
+    cp --parent -n $sofile $CHROOT
+  done
+done
+
+loaders="$(find /lib/ld-* -type l) $(find /lib32/ld-* -type l) $(find /lib64/ld-* -type l)"
+
+for loader in $loaders
+do
+  cp --parent -n $loader $CHROOT
+done
 
 # /usr/share/fonts needs to be taken care of separately because the
 # directory time stamps must be preserved are for fontconfig to trust
@@ -108,3 +181,6 @@ if [ `uname -s` = Linux ]; then
 	cp -r -p /usr/share/ghostscript/fonts usr/share/ghostscript
     fi
 fi
+
+echo "testing if Poco libraries were installed properly"
+sudo chroot $CHROOT /usr/bin/dummy
commit bcad171d21e536e9952bf387b568c8ba88cb7de8
Author:     Henry Castro <hcastro at collabora.com>
AuthorDate: Sat Dec 19 20:09:48 2015 -0500
Commit:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Mon Dec 21 11:18:43 2015 -0500

    loolwsd: deligating to loolbroker and loolkit
    
    Change-Id: I8499540630373a1bee12a5f58fca3ed701ff6404

diff --git a/loolwsd/ChildProcessSession.cpp b/loolwsd/ChildProcessSession.cpp
index 95909afe3..b74138ba0 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 df77fa867..5a64598bc 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 229f78d50..41da9bbde 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 637c2461f..3f7cfee4e 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 fb4af0beb..513e20021 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 ec5ff0d84..4b9329aa5 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;
 
commit 81c346437b6c5980dabb9a70d324a2183a364f74
Author:     Henry Castro <hcastro at collabora.com>
AuthorDate: Sat Dec 19 17:20:04 2015 -0500
Commit:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
CommitDate: Mon Dec 21 11:18:43 2015 -0500

    loolwsd: LOOLBroker process added
    
    Change-Id: Ia7332761766026599b8ef415652874371938d311

diff --git a/loolwsd/.gitignore b/loolwsd/.gitignore
index 2054b6abd..1461eea5d 100644
--- a/loolwsd/.gitignore
+++ b/loolwsd/.gitignore
@@ -32,6 +32,7 @@ lokitclient
 loadtest
 loolwsd
 loolkit
+loolbroker
 sockettransporttest
 
 # Debug output
diff --git a/loolwsd/LOOLBroker.cpp b/loolwsd/LOOLBroker.cpp
new file mode 100644
index 000000000..df77fa867
--- /dev/null
+++ b/loolwsd/LOOLBroker.cpp
@@ -0,0 +1,860 @@
+/* -*- 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/types.h>
+#include <sys/wait.h>
+#include <sys/capability.h>
+
+#include <utime.h>
+#include <ftw.h>
+#include <unistd.h>
+#include <dlfcn.h>
+
+#include <mutex>
+#include <cstring>
+#include <cassert>
+#include <iostream>
+#include <fstream>
+#include <deque>
+
+#include <Poco/Types.h>
+#include <Poco/Random.h>
+#include <Poco/Path.h>
+#include <Poco/File.h>
+#include <Poco/ThreadLocal.h>
+#include <Poco/Process.h>
+#include <Poco/Thread.h>
+#include <Poco/NamedMutex.h>
+
+#include "Util.hpp"
+
+// First include the grist of the helper process - ideally
+// we can avoid execve and share lots of memory here. We
+// can't link to a non-PIC translation unit though, so
+// include to share.
+#define LOOLKIT_NO_MAIN 1
+#include "LOOLKit.cpp"
+
+#define INTERVAL_PROBES 10
+#define MAINTENANCE_INTERVAL 1
+
+#define LIB_SOFFICEAPP  "lib" "sofficeapp" ".so"
+#define LIB_SCLO        "lib" "sclo" ".so"
+#define LIB_SWLO        "lib" "swlo" ".so"
+#define LIB_SDLO        "lib" "sdlo" ".so"
+
+typedef int (LokHookPreInit)  ( const char *install_path, const char *user_profile_path );
+
+using Poco::Path;
+using Poco::File;
+using Poco::ThreadLocal;
+using Poco::Process;
+using Poco::Thread;
+using Poco::ProcessHandle;
+
+const std::string FIFO_FILE = "/tmp/loolwsdfifo";
+const std::string FIFO_BROKER = "/tmp/loolbroker.fifo";
+const std::string BROKER_SUFIX = ".fifo";
+const std::string BROKER_PREFIX = "/tmp/lokit";
+
+static int readerChild = -1;
+static int readerBroker = -1;
+static int timeoutCounter = 0;
+
+static unsigned int forkCounter = 0;
+static unsigned int childCounter = 0;
+
+static std::mutex forkMutex;
+static std::deque<Process::PID> _emptyURL;
+static std::map<Process::PID, int> _childProcesses;
+static std::map<std::string, Process::PID> _cacheURL;
+
+Poco::NamedMutex _namedMutexLOOL("loolwsd");
+
+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)
+            {
+                std::cout << Util::logPrefix() +
+                                                       "link(\"" + fpath + "\",\"" + newPath.toString() + "\") failed: " +
+                                                       strerror(errno) << std::endl;
+                exit(1);
+            }
+            break;
+        case FTW_DP:
+            {
+                struct stat st;
+                if (stat(fpath, &st) == -1)
+                {
+                    std::cout << Util::logPrefix() +
+                                                           "stat(\"" + fpath + "\") failed: " +
+                                                           strerror(errno) << std::endl;
+                    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)
+                {
+                    std::cout << Util::logPrefix() +
+                                                           "utime(\"" + newPath.toString() + "\", &ut) failed: " +
+                                                           strerror(errno) << std::endl;
+                    return 1;
+                }
+            }
+            break;
+        case FTW_DNR:
+            std::cout <<Util::logPrefix() +
+                                                   "Cannot read directory '" + fpath + "'" << std::endl;
+            return 1;
+        case FTW_NS:
+            std::cout <<Util::logPrefix() +
+                                                   "nftw: stat failed for '" + fpath + "'" << std::endl;
+            return 1;
+        case FTW_SLN:
+            std::cout <<Util::logPrefix() +
+                                                         "nftw: symlink to nonexistent file: '" + fpath + "', ignored" << std::endl;
+            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)
+            std::cout << Util::logPrefix() +
+                                                   "linkOrCopy: nftw() failed for '" + source + "'" << std::endl;
+    }
+
+    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)
+        {
+            std::cout << Util::logPrefix() + "cap_get_proc() failed: " + strerror(errno) << std::endl;
+            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)
+        {
+            std::cout << Util::logPrefix() +  "cap_set_flag() failed: " + strerror(errno) << std::endl;
+            exit(1);
+        }
+
+        if (cap_set_proc(caps) == -1)
+        {
+            std::cout << Util::logPrefix() << std::string("cap_set_proc() failed: ") + strerror(errno) << std::endl;
+            exit(1);
+        }
+
+        char *capText = cap_to_text(caps, NULL);
+        std::cout << Util::logPrefix() + "Capabilities now: " + capText << std::endl;
+        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)
+            {
+                std::cout << Util::logPrefix() << std::string("setuid() failed: ") + strerror(errno) << std::endl;
+            }
+        }
+#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;
+            }

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list