[Libreoffice-commits] online.git: 2 commits - loolwsd/ChildSession.cpp loolwsd/ChildSession.hpp loolwsd/Connect.cpp loolwsd/DocumentBroker.cpp loolwsd/DocumentBroker.hpp loolwsd/LOKitClient.cpp loolwsd/LOOLKit.cpp loolwsd/LOOLWSD.cpp loolwsd/protocol.txt loolwsd/test loolwsd/TileCache.cpp loolwsd/Util.cpp loolwsd/Util.hpp

Tor Lillqvist tml at collabora.com
Wed Sep 28 21:43:49 UTC 2016


 loolwsd/ChildSession.cpp    |    6 ++++-
 loolwsd/ChildSession.hpp    |    2 -
 loolwsd/Connect.cpp         |   11 ++++++++++
 loolwsd/DocumentBroker.cpp  |   24 ++++++++++++++++++++++
 loolwsd/DocumentBroker.hpp  |    2 +
 loolwsd/LOKitClient.cpp     |   11 ++++++++++
 loolwsd/LOOLKit.cpp         |   28 +++++++++++++++++++++----
 loolwsd/LOOLWSD.cpp         |   15 +++++++++++++
 loolwsd/TileCache.cpp       |    7 ++----
 loolwsd/Util.cpp            |   46 ++++++++----------------------------------
 loolwsd/Util.hpp            |   28 +++++++++++++++++--------
 loolwsd/protocol.txt        |   10 +++++++--
 loolwsd/test/Makefile.am    |    9 ++++++--
 loolwsd/test/httpwstest.cpp |   48 ++++++++++++++++++++++++++++++++++++++++++++
 14 files changed, 186 insertions(+), 61 deletions(-)

New commits:
commit 96e6ad750260061d179d265b83d8044e6d46f5d5
Author: Tor Lillqvist <tml at collabora.com>
Date:   Wed Sep 28 22:07:07 2016 +0300

    Re-think disk full handling
    
    Instead of trying to inform the sysadmin (which we did not yet try to
    do in any meaningful way), inform all connected clients (even those
    editing other documents).
    
    We use 'error: cmd=internal kind=diskfull' as the message to the
    clients. The loleaflet code needs to be updated to handle that
    carefully by displaying a very prominent message that tells the user
    that all bets are off.
    
    Also add a unit test for the functionality.
    
    Document the new protocol details.
    
    The code for this alert functionalty became a bit less elegant than I
    like because of the way we include Util.cpp in the unit test 'test'
    program.
    
    Still need to add code to check for disk full in more places, not just
    when saving a cached tile or font. Probably we should even actually
    check for disk space on the file system(s) we use getting alarmingly
    low, not just check for file writing operations that fail. Later.

diff --git a/loolwsd/ChildSession.cpp b/loolwsd/ChildSession.cpp
index b1556a5..7ae8b7e 100644
--- a/loolwsd/ChildSession.cpp
+++ b/loolwsd/ChildSession.cpp
@@ -722,7 +722,11 @@ bool ChildSession::unoCommand(const char* /*buffer*/, int /*length*/, StringToke
 
     _loKitDocument->setView(_viewId);
 
-    if (tokens.count() == 2)
+    if (tokens.count() == 2 && tokens[1] == ".uno:fakeDiskFull")
+    {
+        Util::alertAllUsers("internal", "diskfull");
+    }
+    else if (tokens.count() == 2)
     {
         _loKitDocument->postUnoCommand(tokens[1].c_str(), nullptr, bNotify);
     }
diff --git a/loolwsd/Connect.cpp b/loolwsd/Connect.cpp
index eb91903..211e56e 100644
--- a/loolwsd/Connect.cpp
+++ b/loolwsd/Connect.cpp
@@ -244,6 +244,17 @@ private:
     URI _uri;
 };
 
+namespace Util
+{
+
+void alertAllUsers(const std::string& cmd, const std::string& kind)
+{
+    std::cout << "error: cmd=" << cmd << " kind=" << kind << std::endl;
+    (void) kind;
+}
+
+}
+
 POCO_APP_MAIN(Connect)
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/loolwsd/DocumentBroker.cpp b/loolwsd/DocumentBroker.cpp
index d1dd3ac..ba2dd04 100644
--- a/loolwsd/DocumentBroker.cpp
+++ b/loolwsd/DocumentBroker.cpp
@@ -15,6 +15,7 @@
 
 #include <Poco/Path.h>
 #include <Poco/SHA1Engine.h>
+#include <Poco/StringTokenizer.h>
 
 #include "ClientSession.hpp"
 #include "Exceptions.hpp"
@@ -28,6 +29,8 @@
 
 using namespace LOOLProtocol;
 
+using Poco::StringTokenizer;
+
 void ChildProcess::socketProcessor()
 {
     IoUtil::SocketProcessor(_ws,
@@ -443,6 +446,16 @@ size_t DocumentBroker::removeSession(const std::string& id)
     return _sessions.size();
 }
 
+void DocumentBroker::alertAllUsersOfDocument(const std::string& cmd, const std::string& kind)
+{
+    std::lock_guard<std::mutex> lock(_mutex);
+
+    for (auto& it: _sessions)
+    {
+        it.second->sendTextFrame("error: cmd=" + cmd + " kind=" + kind);
+    }
+}
+
 bool DocumentBroker::handleInput(const std::vector<char>& payload)
 {
     const auto msg = LOOLProtocol::getAbbreviatedMessage(payload);
@@ -458,6 +471,17 @@ bool DocumentBroker::handleInput(const std::vector<char>& payload)
     {
        handleTileCombinedResponse(payload);
     }
+    else if (msg.find("errortoall:") == 0)
+    {
+        StringTokenizer tokens(msg, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+        assert(tokens.count() == 3);
+        std::string cmd, kind;
+        LOOLProtocol::getTokenString(tokens, "cmd", cmd);
+        assert(cmd != "");
+        LOOLProtocol::getTokenString(tokens, "kind", kind);
+        assert(kind != "");
+        Util::alertAllUsers(cmd, kind);
+    }
     else
     {
         Log::error("Unexpected message: [" + msg + "].");
diff --git a/loolwsd/DocumentBroker.hpp b/loolwsd/DocumentBroker.hpp
index a547a32..16008f4 100644
--- a/loolwsd/DocumentBroker.hpp
+++ b/loolwsd/DocumentBroker.hpp
@@ -201,6 +201,8 @@ public:
     /// Removes a session by ID. Returns the new number of sessions.
     size_t removeSession(const std::string& id);
 
+    void alertAllUsersOfDocument(const std::string& cmd, const std::string& kind);
+
     /// Invalidate the cursor position.
     void invalidateCursor(int x, int y, int w, int h)
     {
diff --git a/loolwsd/LOKitClient.cpp b/loolwsd/LOKitClient.cpp
index b882b79..06d0a33 100644
--- a/loolwsd/LOKitClient.cpp
+++ b/loolwsd/LOKitClient.cpp
@@ -206,6 +206,17 @@ protected:
     }
 };
 
+namespace Util
+{
+
+void alertAllUsers(const std::string& cmd, const std::string& kind)
+{
+    std::cout << "error: cmd=" << cmd << " kind=" << kind << std::endl;
+    (void) kind;
+}
+
+}
+
 POCO_APP_MAIN(LOKitClient)
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp
index da06fb8..c37f2c6 100644
--- a/loolwsd/LOOLKit.cpp
+++ b/loolwsd/LOOLKit.cpp
@@ -89,6 +89,10 @@ using Poco::Util::Application;
 
 using namespace LOOLProtocol;
 
+// We only host a single document in our lifetime.
+class Document;
+static std::shared_ptr<Document> document;
+
 namespace
 {
     typedef enum { COPY_ALL, COPY_LO, COPY_NO_USR } LinkOrCopyType;
@@ -800,6 +804,13 @@ public:
         ws->sendFrame(response.data(), length, WebSocket::FRAME_BINARY);
     }
 
+    void sendTextFrame(const std::string& message)
+    {
+        std::lock_guard<std::mutex> lock(_mutex);
+
+        _ws->sendFrame(message.data(), message.size());
+    }
+
 private:
 
     static void GlobalCallback(const int nType, const char* pPayload, void* pData)
@@ -1339,9 +1350,6 @@ void lokit_main(const std::string& childRoot,
     assert(!loTemplate.empty());
     assert(!loSubPath.empty());
 
-    // We only host a single document in our lifetime.
-    std::shared_ptr<Document> document;
-
     // Ideally this will be a random ID, but forkit will cleanup
     // our jail directory when we die, and it's simpler to know
     // the jailId (i.e. the path) implicitly by knowing our pid.
@@ -1507,7 +1515,7 @@ void lokit_main(const std::string& childRoot,
 
         const std::string socketName = "ChildControllerWS";
         IoUtil::SocketProcessor(ws,
-                [&socketName, &ws, &document, &loKit, &queue](const std::vector<char>& data)
+                [&socketName, &ws, &loKit, &queue](const std::vector<char>& data)
                 {
                     std::string message(data.data(), data.size());
 
@@ -1568,7 +1576,7 @@ void lokit_main(const std::string& childRoot,
                     return true;
                 },
                 []() {},
-                [&document]()
+                []()
                 {
                     if (document && document->canDiscard())
                     {
@@ -1676,4 +1684,14 @@ bool globalPreinit(const std::string &loTemplate)
     return true;
 }
 
+namespace Util
+{
+
+void alertAllUsers(const std::string& cmd, const std::string& kind)
+{
+    document->sendTextFrame("errortoall: cmd=" + cmd + " kind=" + kind);
+}
+
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index d4dd59b..951a927 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -2001,6 +2001,21 @@ void UnitWSD::testHandleRequest(TestRequest type, UnitHTTPServerRequest& request
     }
 }
 
+namespace Util
+{
+
+void alertAllUsers(const std::string& cmd, const std::string& kind)
+{
+    std::lock_guard<std::mutex> docBrokersLock(docBrokersMutex);
+
+    for (auto& brokerIt : docBrokers)
+    {
+        brokerIt.second->alertAllUsersOfDocument(cmd, kind);
+    }
+}
+
+}
+
 POCO_SERVER_MAIN(LOOLWSD)
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/loolwsd/TileCache.cpp b/loolwsd/TileCache.cpp
index 91b95cd..ca8a82a 100644
--- a/loolwsd/TileCache.cpp
+++ b/loolwsd/TileCache.cpp
@@ -155,9 +155,9 @@ void TileCache::saveTileAndNotify(const TileDesc& tile, const char *data, const
                                                : cacheFileName(tile));
 
     // Ignore if we can't save the tile, things will work anyway, but slower. An error indication
-    // supposed to reach a sysadmin has been produced in that case.
+    // has been supposed to be sent to all users in that case.
     const auto fileName = _cacheDir + "/" + cachedName;
-    if (Util::saveDataToFileSafely(fileName, data, size, Poco::Message::PRIO_CRITICAL))
+    if (Util::saveDataToFileSafely(fileName, data, size))
         Log::trace() << "Saved cache tile: " << fileName << Log::end;
 
     // Notify subscribers, if any.
@@ -277,8 +277,7 @@ void TileCache::saveRendering(const std::string& name, const std::string& dir, c
 
     const std::string fileName = dirName + "/" + name;
 
-    // Is failing to save a font as important as failing to save cached tiles?
-    Util::saveDataToFileSafely(fileName, data, size, Poco::Message::PRIO_CRITICAL);
+    Util::saveDataToFileSafely(fileName, data, size);
 }
 
 std::unique_ptr<std::fstream> TileCache::lookupRendering(const std::string& name, const std::string& dir)
diff --git a/loolwsd/Util.cpp b/loolwsd/Util.cpp
index 3f25ae4..c3a5786 100644
--- a/loolwsd/Util.cpp
+++ b/loolwsd/Util.cpp
@@ -36,7 +36,6 @@
 #include <Poco/Exception.h>
 #include <Poco/Format.h>
 #include <Poco/Net/WebSocket.h>
-#include <Poco/Message.h>
 #include <Poco/Process.h>
 #include <Poco/RandomStream.h>
 #include <Poco/TemporaryFile.h>
@@ -46,6 +45,7 @@
 
 #include "Common.hpp"
 #include "Log.hpp"
+#include "Util.hpp"
 
 std::atomic<bool> TerminationFlag(false);
 
@@ -108,12 +108,10 @@ namespace rng
 
 namespace
 {
-    void alertSysadminOrLogNormally(const std::string& message, const std::string& tag, Poco::Message::Priority priority)
+    void alertAllUsersAndLog(const std::string& message, const std::string& cmd, const std::string& kind)
     {
-        if (priority <= Poco::Message::PRIO_CRITICAL)
-            Util::alertSysadminWithoutSpamming(message, tag, 6);
-        else
-            Log::error(message + " Removing.");
+        Log::error(message + " Removing.");
+        Util::alertAllUsers(cmd, kind);
     }
 }
 
@@ -157,7 +155,7 @@ namespace Util
         return std::getenv("DISPLAY") != nullptr;
     }
 
-    bool saveDataToFileSafely(std::string fileName, const char *data, size_t size, Poco::Message::Priority priority)
+    bool saveDataToFileSafely(std::string fileName, const char *data, size_t size)
     {
         const auto tempFileName = fileName + ".temp";
         std::fstream outStream(tempFileName, std::ios::out);
@@ -165,7 +163,7 @@ namespace Util
         // If we can't create the file properly, just remove it
         if (!outStream.good())
         {
-            alertSysadminOrLogNormally("Creating " + tempFileName + " failed, disk full?", "diskfull?", priority);
+            alertAllUsersAndLog("Creating " + tempFileName + " failed, disk full?", "internal", "diskfull");
             // Try removing both just in case
             std::remove(tempFileName.c_str());
             std::remove(fileName.c_str());
@@ -176,7 +174,7 @@ namespace Util
             outStream.write(data, size);
             if (!outStream.good())
             {
-                alertSysadminOrLogNormally("Writing to " + tempFileName + " failed, disk full?", "diskfull?", priority);
+                alertAllUsersAndLog("Writing to " + tempFileName + " failed, disk full?", "internal", "diskfull");
                 outStream.close();
                 std::remove(tempFileName.c_str());
                 std::remove(fileName.c_str());
@@ -187,7 +185,7 @@ namespace Util
                 outStream.close();
                 if (!outStream.good())
                 {
-                    alertSysadminOrLogNormally("Closing " + tempFileName + " failed, disk full?", "diskfull?", priority);
+                    alertAllUsersAndLog("Closing " + tempFileName + " failed, disk full?", "internal", "diskfull");
                     std::remove(tempFileName.c_str());
                     std::remove(fileName.c_str());
                     return false;
@@ -202,7 +200,7 @@ namespace Util
                     }
                     else
                     {
-                        alertSysadminOrLogNormally("Renaming " + tempFileName + " to " + fileName + " failed, disk full?", "diskfull?", priority);
+                        alertAllUsersAndLog("Renaming " + tempFileName + " to " + fileName + " failed, disk full?", "internal", "diskfull");
                         std::remove(tempFileName.c_str());
                         std::remove(fileName.c_str());
                         return false;
@@ -212,32 +210,6 @@ namespace Util
         }
     }
 
-    void alertSysadminWithoutSpamming(const std::string& message, const std::string& tag, int maxMessagesPerDay)
-    {
-        static std::map<std::string, std::chrono::steady_clock::time_point> timeStamp;
-
-        const auto now = std::chrono::steady_clock::now();
-        const auto minInterval = std::chrono::seconds(24 * 60 * 60) / maxMessagesPerDay;
-
-        if (timeStamp.find(tag) == timeStamp.end() ||
-            timeStamp[tag] < now - minInterval)
-        {
-            // FIXME: Come up with something here that actually is a good way to notify the sysadmin
-            // so that this function actually does what it says on the tin. Is there some direct
-            // systemd way to log really important messages? And how to use that then conditionally
-            // on whether we actually are running under systemd, or just normally, for a developer
-            // or at some end-user that doesn't use systemd for LOOL.
-
-            // Or should we extend our Log API to also have the CRITICAL level, and then get all our
-            // normal decorations in the logging also for this? On the other hand, it is a bit
-            // redundant actually to have our logging output timestamps, for instance, as systemd's
-            // logging mechanism automatically attaches timestamps to output from processes it runs
-            // anyway, doesn't it?
-            Log::logger().critical(message);
-            timeStamp[tag] = now;
-        }
-    }
-
     const char *signalName(const int signo)
     {
         switch (signo)
diff --git a/loolwsd/Util.hpp b/loolwsd/Util.hpp
index 8d9fab9..53c28a9 100644
--- a/loolwsd/Util.hpp
+++ b/loolwsd/Util.hpp
@@ -21,7 +21,6 @@
 
 #include <Poco/File.h>
 #include <Poco/Net/WebSocket.h>
-#include <Poco/Message.h>
 #include <Poco/Path.h>
 #include <Poco/Process.h>
 #include <Poco/RegularExpression.h>
@@ -54,14 +53,25 @@ namespace Util
     // to a temporary file in the same directory that is then atomically renamed to the desired name
     // if everything goes well. In case of any error, both the destination file (if it already
     // exists) and the temporary file (if was created, or existed already) are removed. Return true
-    // if everything succeeded. If priority is PRIO_CRITICAL or PRIO_FATAL, we will try to make sure
-    // an error message reaches a sysadmin. Such a message will be produced at most once every four
-    // hours during the runtime of the process to make it less likely they are ignored as spam.
-    bool saveDataToFileSafely(std::string fileName, const char *data, size_t size, Poco::Message::Priority priority);
-
-    // Log the message with priority PRIO_CRITICAL. Don't log messages with the same tag more often
-    // than maxMessagesPerDay.
-    void alertSysadminWithoutSpamming(const std::string& message, const std::string& tag, int maxMessagesPerDay);
+    // if everything succeeded.
+    bool saveDataToFileSafely(std::string fileName, const char *data, size_t size);
+
+    // We work around some of the mess of using the same sources both on the server side and in unit
+    // tests with conditional compilation based on BUILDING_TESTS.
+
+#ifndef BUILDING_TESTS
+    // Send a 'error:' message with the specified cmd and kind parameters to all connected
+    // clients. This function can be called either in loolwsd or loolkit processes, even if only
+    // loolwsd obviously has contact with the actual clients; in loolkit it will be forwarded to
+    // loolwsd for redistribution. (This function must be implemented separately in each program
+    // that uses it, it is not in Util.cpp.)
+    void alertAllUsers(const std::string& cmd, const std::string& kind);
+#else
+    // No-op implementation in the test programs
+    inline void alertAllUsers(const std::string&, const std::string&)
+    {
+    }
+#endif
 
     /// Assert that a lock is already taken.
     template <typename T>
diff --git a/loolwsd/protocol.txt b/loolwsd/protocol.txt
index a507a32..c507443 100644
--- a/loolwsd/protocol.txt
+++ b/loolwsd/protocol.txt
@@ -211,8 +211,9 @@ error: cmd=<command> kind=<kind> [code=<error_code>]
 <freeErrorText>
 
     <command> is the command part of the corresponding client->server
-    message that caused the error. <kind> is some single-word
-    classification
+    message that caused the error. <command> can also be 'internal'
+    for errors generated without directly corresponding to a client
+    message. <kind> is some single-word classification
 
     <code> (when provided) further specifies the error as forwarded from
     LibreOffice
@@ -347,6 +348,11 @@ curpart: part=<partNumber>
     needs to act on in addition to passing them on to the client, like
     invalidatetiles:
 
+errortoall: cmd=<command> kind=<kind> [code=<error_code>]
+
+    Causes the parent to send the corresponding error: message to all
+    clients.
+
 nextmessage: size=<upperlimit>
 
     each tile: message sent from the child to the parent is preceded
diff --git a/loolwsd/test/Makefile.am b/loolwsd/test/Makefile.am
index d8e152e..b277644 100644
--- a/loolwsd/test/Makefile.am
+++ b/loolwsd/test/Makefile.am
@@ -15,7 +15,12 @@ noinst_LTLIBRARIES = \
 
 MAGIC_TO_FORCE_SHLIB_CREATION = -rpath /dummy
 AM_LDFLAGS = -pthread -module $(MAGIC_TO_FORCE_SHLIB_CREATION)
-AM_CPPFLAGS = -pthread -I$(top_srcdir)
+
+# We work around some of the mess of using the same sources both on
+# the server side and here in unit tests with conditional compilation
+# based on BUILDING_TESTS
+
+AM_CPPFLAGS = -pthread -I$(top_srcdir) -DBUILDING_TESTS
 
 wsd_sources = \
             ../IoUtil.cpp \
@@ -27,7 +32,7 @@ wsd_sources = \
             ../Unit.cpp \
             ../Util.cpp
 
-test_CPPFLAGS = -DTDOC=\"$(abs_top_srcdir)/test/data\" -I$(top_srcdir)
+test_CPPFLAGS = -DTDOC=\"$(abs_top_srcdir)/test/data\" -I$(top_srcdir) -DBUILDING_TESTS
 test_SOURCES = TileCacheTests.cpp WhiteBoxTests.cpp integration-http-server.cpp \
                httpwstest.cpp httpcrashtest.cpp httpwserror.cpp test.cpp $(wsd_sources)
 test_LDADD = $(CPPUNIT_LIBS)
diff --git a/loolwsd/test/httpwstest.cpp b/loolwsd/test/httpwstest.cpp
index 91df94b..5d07755 100644
--- a/loolwsd/test/httpwstest.cpp
+++ b/loolwsd/test/httpwstest.cpp
@@ -98,6 +98,7 @@ class HTTPWSTest : public CPPUNIT_NS::TestFixture
     CPPUNIT_TEST(testGraphicViewSelection);
     CPPUNIT_TEST(testGraphicInvalidate);
     CPPUNIT_TEST(testCursorPosition);
+    CPPUNIT_TEST(testAlertAllUsers);
 
     CPPUNIT_TEST_SUITE_END();
 
@@ -141,6 +142,7 @@ class HTTPWSTest : public CPPUNIT_NS::TestFixture
     void testGraphicViewSelection();
     void testGraphicInvalidate();
     void testCursorPosition();
+    void testAlertAllUsers();
 
     void loadDoc(const std::string& documentURL);
 
@@ -2209,6 +2211,52 @@ void HTTPWSTest::testCursorPosition()
     }
 }
 
+void HTTPWSTest::testAlertAllUsers()
+{
+    // Load two documents, each in two sessions. Tell one session to fake a disk full
+    // situation. Expect to get the corresponding error back in all sessions.
+
+    try
+    {
+        std::string docPath[2];
+        std::string docURL[2];
+
+        getDocumentPathAndURL("Example.odt", docPath[0], docURL[0]);
+        getDocumentPathAndURL("hello.odt", docPath[1], docURL[1]);
+
+        Poco::Net::HTTPRequest* request[2];
+
+        for (int i = 0; i < 2; i++)
+            request[i] = new Poco::Net::HTTPRequest(Poco::Net::HTTPRequest::HTTP_GET, docURL[i]);
+
+        std::shared_ptr<Poco::Net::WebSocket> socket[4];
+        for (int i = 0; i < 4; i++)
+        {
+            socket[i] = connectLOKit(_uri, *(request[i/2]), _response);
+            sendTextFrame(socket[i], "load url=" + docURL[i/2]);
+        }
+
+        sendTextFrame(socket[0], "uno .uno:fakeDiskFull");
+
+        for (int i = 0; i < 4; i++)
+        {
+            std::string response;
+            getResponseMessage(socket[i], "error:", response, false);
+            Poco::StringTokenizer tokens(response, " ", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM);
+            std::string cmd;
+            LOOLProtocol::getTokenString(tokens, "cmd", cmd);
+            CPPUNIT_ASSERT_EQUAL(std::string("internal"), cmd);
+            std::string kind;
+            LOOLProtocol::getTokenString(tokens, "kind", kind);
+            CPPUNIT_ASSERT_EQUAL(std::string("diskfull"), kind);
+        }
+    }
+    catch (const Poco::Exception& exc)
+    {
+        CPPUNIT_FAIL(exc.displayText());
+    }
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(HTTPWSTest);
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 075c487001afe2b0038f4e2971479adb54ab4e53
Author: Tor Lillqvist <tml at collabora.com>
Date:   Wed Sep 28 20:15:51 2016 +0300

    Fix comment. There can be several ChildSessions in a kit process

diff --git a/loolwsd/ChildSession.hpp b/loolwsd/ChildSession.hpp
index 0ada61e..87a754f 100644
--- a/loolwsd/ChildSession.hpp
+++ b/loolwsd/ChildSession.hpp
@@ -45,7 +45,7 @@ public:
     void notifyViewInfo() = 0;
 };
 
-/// Represents the session to the WSD process, in a Kit process.
+/// Represents a session to the WSD process, in a Kit process. Note that this is not a singleton.
 class ChildSession final : public LOOLSession
 {
 public:


More information about the Libreoffice-commits mailing list