[Libreoffice-commits] online.git: Branch 'private/mmeeks/fixing' - 75 commits - common/Common.hpp common/IoUtil.cpp common/LOOLWebSocket.hpp common/Session.cpp common/Session.hpp common/Util.cpp common/Util.hpp configure.ac debian/loolwsd.postinst.in etc/cert.pem etc/key.pem kit/Kit.cpp loleaflet/dist loleaflet/po loleaflet/src loolwsd.spec.in loolwsd.xml.in Makefile.am net/clientnb.cpp net/Socket.cpp net/Socket.hpp net/Ssl.cpp net/Ssl.hpp net/SslSocket.hpp net/WebSocketHandler.hpp scripts/downloadpootle.sh test/helpers.hpp test/httpcrashtest.cpp test/httpwserror.cpp test/httpwstest.cpp test/integration-http-server.cpp test/Makefile.am test/run_unit.sh.in test/TileCacheTests.cpp wsd/Admin.cpp wsd/Admin.hpp wsd/AdminModel.cpp wsd/AdminModel.hpp wsd/ClientSession.cpp wsd/ClientSession.hpp wsd/DocumentBroker.cpp wsd/DocumentBroker.hpp wsd/LOOLWSD.cpp wsd/LOOLWSD.hpp wsd/SenderQueue.hpp wsd/Storage.cpp wsd/TestStubs.cpp wsd/TileCache.cpp

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


Rebased ref, commits from common ancestor:
commit 2e372b70b32d4e052458547daa229c537442774f
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Thu Apr 6 17:58:41 2017 +0100
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Thu Apr 6 17:58:41 2017 +0100

    Let the DocBroker thread clean itself up and expire.

diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index a5a995dfd..0ee997389 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -241,6 +241,18 @@ void DocumentBroker::pollThread()
             LOG_INF("No more sessions in doc [" << _docKey << "]. Terminating.");
             _stop = true;
         }
+
+        // Remove idle documents after 1 hour.
+        const bool idle = getIdleTimeSecs() >= 3600;
+
+        // Cleanup used and dead entries.
+        if ((isLoaded() || _markToDestroy) &&
+            (getSessionsCount() == 0 || !isAlive() || idle))
+        {
+            LOG_INF("Terminating " << (idle ? "idle" : "dead") <<
+                    " DocumentBroker for docKey [" << getDocKey() << "].");
+            _stop = true;
+        }
     }
 
     LOG_INF("Finished polling doc [" << _docKey << "]. stop: " << _stop << ", continuePolling: " <<
diff --git a/wsd/DocumentBroker.hpp b/wsd/DocumentBroker.hpp
index d05437e9c..fd8d20e80 100644
--- a/wsd/DocumentBroker.hpp
+++ b/wsd/DocumentBroker.hpp
@@ -304,7 +304,7 @@ public:
     void handleTileCombinedResponse(const std::vector<char>& payload);
 
     void destroyIfLastEditor(const std::string& id);
-    bool isMarkedToDestroy() const { return _markToDestroy; }
+    bool isMarkedToDestroy() const { return _markToDestroy || _stop; }
 
     bool handleInput(const std::vector<char>& payload);
 
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index e5d4cb689..439ab67ed 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -235,33 +235,15 @@ void cleanupDocBrokers()
     {
         auto docBroker = it->second;
 
-        // If document busy at the moment, cleanup later.
-        auto lock = docBroker->getDeferredLock();
-        if (lock.try_lock())
+        // Remove only when not alive.
+        if (!docBroker->isAlive())
         {
-            // Remove idle documents after 1 hour.
-            const bool idle = (docBroker->getIdleTimeSecs() >= 3600);
-
-            // Cleanup used and dead entries.
-            if ((docBroker->isLoaded() || docBroker->isMarkedToDestroy()) &&
-                (docBroker->getSessionsCount() == 0 || !docBroker->isAlive() || idle))
-            {
-                LOG_INF("Terminating " << (idle ? "idle" : "dead") <<
-                        " DocumentBroker for docKey [" << it->first << "].");
-                docBroker->stop();
-
-                // Remove only when not alive.
-                if (!docBroker->isAlive())
-                {
-                    LOG_INF("Removing " << (idle ? "idle" : "dead") <<
-                            " DocumentBroker for docKey [" << it->first << "].");
-                    it = DocBrokers.erase(it);
-                    continue;
-                }
-            }
+            LOG_INF("Removing DocumentBroker for docKey [" << it->first << "].");
+            it = DocBrokers.erase(it);
+            continue;
+        } else {
+            ++it;
         }
-
-        ++it;
     }
 
     if (count != DocBrokers.size())
commit fb4fbdd575d6971c92a5222da1fe245f5791bd78
Author:     Jan Holesovsky <kendy at collabora.com>
AuthorDate: Tue Apr 4 19:54:08 2017 +0200
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Thu Apr 6 16:58:42 2017 +0100

    Disable the unreliable unit tests.
    
    Change-Id: I1de9cc566b1b88563152aa36a5505867e46ea2af

diff --git a/test/TileCacheTests.cpp b/test/TileCacheTests.cpp
index 59dadfaa9..128f559dd 100644
--- a/test/TileCacheTests.cpp
+++ b/test/TileCacheTests.cpp
@@ -61,7 +61,7 @@ class TileCacheTests : public CPPUNIT_NS::TestFixture
     CPPUNIT_TEST(testImpressTiles);
     CPPUNIT_TEST(testClientPartImpress);
     CPPUNIT_TEST(testClientPartCalc);
-    CPPUNIT_TEST(testTilesRenderedJustOnce);
+    // FIXME CPPUNIT_TEST(testTilesRenderedJustOnce);
     // CPPUNIT_TEST(testTilesRenderedJustOnceMultiClient); // always fails, seems complicated to fix
 #if ENABLE_DEBUG
     CPPUNIT_TEST(testSimultaneousTilesRenderedJustOnce);
diff --git a/test/httpcrashtest.cpp b/test/httpcrashtest.cpp
index b6230d5a6..deeed9907 100644
--- a/test/httpcrashtest.cpp
+++ b/test/httpcrashtest.cpp
@@ -56,7 +56,7 @@ class HTTPCrashTest : public CPPUNIT_NS::TestFixture
     CPPUNIT_TEST_SUITE(HTTPCrashTest);
 
     CPPUNIT_TEST(testBarren);
-    CPPUNIT_TEST(testCrashKit);
+    // FIXME CPPUNIT_TEST(testCrashKit);
     CPPUNIT_TEST(testRecoverAfterKitCrash);
     CPPUNIT_TEST(testCrashForkit);
 
diff --git a/test/httpwserror.cpp b/test/httpwserror.cpp
index d658905db..254b2982c 100644
--- a/test/httpwserror.cpp
+++ b/test/httpwserror.cpp
@@ -37,7 +37,7 @@ class HTTPWSError : public CPPUNIT_NS::TestFixture
     CPPUNIT_TEST_SUITE(HTTPWSError);
 
     CPPUNIT_TEST(testBadDocLoadFail);
-    CPPUNIT_TEST(testMaxDocuments);
+    // FIXME CPPUNIT_TEST(testMaxDocuments);
     CPPUNIT_TEST(testMaxConnections);
     CPPUNIT_TEST(testMaxViews);
 
diff --git a/test/httpwstest.cpp b/test/httpwstest.cpp
index 1be351408..27b698d78 100644
--- a/test/httpwstest.cpp
+++ b/test/httpwstest.cpp
@@ -57,7 +57,7 @@ class HTTPWSTest : public CPPUNIT_NS::TestFixture
     CPPUNIT_TEST_SUITE(HTTPWSTest);
 
     CPPUNIT_TEST(testBadRequest);
-    CPPUNIT_TEST(testHandshake);
+    // FIXME CPPUNIT_TEST(testHandshake);
     CPPUNIT_TEST(testCloseAfterClose);
     CPPUNIT_TEST(testConnectNoLoad);
     CPPUNIT_TEST(testLoadSimple);
@@ -82,23 +82,23 @@ class HTTPWSTest : public CPPUNIT_NS::TestFixture
     CPPUNIT_TEST(testPasswordProtectedOOXMLDocument);
     CPPUNIT_TEST(testPasswordProtectedBinaryMSOfficeDocument);
     CPPUNIT_TEST(testInsertDelete);
-    CPPUNIT_TEST(testSlideShow);
+    // FIXME CPPUNIT_TEST(testSlideShow);
     CPPUNIT_TEST(testInactiveClient);
     CPPUNIT_TEST(testMaxColumn);
     CPPUNIT_TEST(testMaxRow);
 //    CPPUNIT_TEST(testInsertAnnotationWriter);
 //    CPPUNIT_TEST(testEditAnnotationWriter);
-    CPPUNIT_TEST(testInsertAnnotationCalc);
+    // FIXME CPPUNIT_TEST(testInsertAnnotationCalc);
     CPPUNIT_TEST(testCalcEditRendering);
     CPPUNIT_TEST(testFontList);
     CPPUNIT_TEST(testStateUnoCommandWriter);
     CPPUNIT_TEST(testStateUnoCommandCalc);
     CPPUNIT_TEST(testStateUnoCommandImpress);
-    CPPUNIT_TEST(testColumnRowResize);
-    CPPUNIT_TEST(testOptimalResize);
+    // FIXME CPPUNIT_TEST(testColumnRowResize);
+    // FIXME CPPUNIT_TEST(testOptimalResize);
     CPPUNIT_TEST(testInvalidateViewCursor);
     CPPUNIT_TEST(testViewCursorVisible);
-    CPPUNIT_TEST(testCellViewCursor);
+    // FIXME CPPUNIT_TEST(testCellViewCursor);
     CPPUNIT_TEST(testGraphicViewSelectionWriter);
     CPPUNIT_TEST(testGraphicViewSelectionCalc);
     CPPUNIT_TEST(testGraphicViewSelectionImpress);
diff --git a/test/integration-http-server.cpp b/test/integration-http-server.cpp
index 3530ed577..717862053 100644
--- a/test/integration-http-server.cpp
+++ b/test/integration-http-server.cpp
@@ -44,7 +44,7 @@ class HTTPServerTest : public CPPUNIT_NS::TestFixture
     CPPUNIT_TEST(testLoleafletPost);
     CPPUNIT_TEST(testScriptsAndLinksGet);
     CPPUNIT_TEST(testScriptsAndLinksPost);
-    CPPUNIT_TEST(testConvertTo);
+    // FIXME CPPUNIT_TEST(testConvertTo);
 
     CPPUNIT_TEST_SUITE_END();
 
commit 3d945a5c3846d662e878a5daace5554704e0e586
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Thu Apr 6 16:35:55 2017 +0100
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Thu Apr 6 16:35:55 2017 +0100

    Revert "Don't cleanup DocumentBrokers that still have their thread running."
    
    This reverts commit df8dc43be4980302d4287c0692d02cf4fe6ca253.
    
    DocumentBroker::isAlive already checks _threadFinished.

diff --git a/net/Socket.hpp b/net/Socket.hpp
index 422387513..c726f337a 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -500,9 +500,6 @@ public:
     /// Stop and join the polling thread before returning (if active)
     void joinThread();
 
-    /// Did our thread complete its execution
-    bool isThreadFinished() { return _threadFinished; }
-
 private:
     /// Initialize the poll fds array with the right events
     void setupPollFds(std::chrono::steady_clock::time_point now,
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 9515fbb4d..a5a995dfd 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -305,11 +305,6 @@ DocumentBroker::~DocumentBroker()
     _childProcess.reset();
 }
 
-bool DocumentBroker::isThreadFinished()
-{
-    return _poll->isThreadFinished();
-}
-
 void DocumentBroker::joinThread()
 {
     _poll->joinThread();
diff --git a/wsd/DocumentBroker.hpp b/wsd/DocumentBroker.hpp
index 11d50174e..d05437e9c 100644
--- a/wsd/DocumentBroker.hpp
+++ b/wsd/DocumentBroker.hpp
@@ -227,9 +227,6 @@ public:
     /// Thread safe termination of this broker if it has a lingering thread
     void joinThread();
 
-    /// Is our polling thread safely out of the way
-    bool isThreadFinished();
-
     /// Loads a document from the public URI into the jail.
     bool load(const std::shared_ptr<ClientSession>& session, const std::string& jailId);
     bool isLoaded() const { return _isLoaded; }
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 1c4464625..e5d4cb689 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -250,8 +250,8 @@ void cleanupDocBrokers()
                         " DocumentBroker for docKey [" << it->first << "].");
                 docBroker->stop();
 
-                // Remove only on next pass when the thread is finished.
-                if (docBroker->isThreadFinished() && !docBroker->isAlive())
+                // Remove only when not alive.
+                if (!docBroker->isAlive())
                 {
                     LOG_INF("Removing " << (idle ? "idle" : "dead") <<
                             " DocumentBroker for docKey [" << it->first << "].");
commit df8dc43be4980302d4287c0692d02cf4fe6ca253
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Wed Apr 5 21:48:51 2017 +0100
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Thu Apr 6 16:24:54 2017 +0100

    Don't cleanup DocumentBrokers that still have their thread running.
    
    Plenty of time to do that next time around the cleanup.
    We should still, really be doing the majority of the timeout work
    inside the DocumentBroker poll itself.

diff --git a/net/Socket.hpp b/net/Socket.hpp
index c726f337a..422387513 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -500,6 +500,9 @@ public:
     /// Stop and join the polling thread before returning (if active)
     void joinThread();
 
+    /// Did our thread complete its execution
+    bool isThreadFinished() { return _threadFinished; }
+
 private:
     /// Initialize the poll fds array with the right events
     void setupPollFds(std::chrono::steady_clock::time_point now,
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index a5a995dfd..9515fbb4d 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -305,6 +305,11 @@ DocumentBroker::~DocumentBroker()
     _childProcess.reset();
 }
 
+bool DocumentBroker::isThreadFinished()
+{
+    return _poll->isThreadFinished();
+}
+
 void DocumentBroker::joinThread()
 {
     _poll->joinThread();
diff --git a/wsd/DocumentBroker.hpp b/wsd/DocumentBroker.hpp
index d05437e9c..11d50174e 100644
--- a/wsd/DocumentBroker.hpp
+++ b/wsd/DocumentBroker.hpp
@@ -227,6 +227,9 @@ public:
     /// Thread safe termination of this broker if it has a lingering thread
     void joinThread();
 
+    /// Is our polling thread safely out of the way
+    bool isThreadFinished();
+
     /// Loads a document from the public URI into the jail.
     bool load(const std::shared_ptr<ClientSession>& session, const std::string& jailId);
     bool isLoaded() const { return _isLoaded; }
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index e5d4cb689..1c4464625 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -250,8 +250,8 @@ void cleanupDocBrokers()
                         " DocumentBroker for docKey [" << it->first << "].");
                 docBroker->stop();
 
-                // Remove only when not alive.
-                if (!docBroker->isAlive())
+                // Remove only on next pass when the thread is finished.
+                if (docBroker->isThreadFinished() && !docBroker->isAlive())
                 {
                     LOG_INF("Removing " << (idle ? "idle" : "dead") <<
                             " DocumentBroker for docKey [" << it->first << "].");
commit 2124ec30c61917f934b1af77e69fbc2e457eb854
Author:     Pranav Kant <pranavk at collabora.co.uk>
AuthorDate: Thu Apr 6 20:37:40 2017 +0530
Commit:     Pranav Kant <pranavk at collabora.co.uk>
CommitDate: Thu Apr 6 20:40:51 2017 +0530

    net: Disable deflate unconditionally
    
    First reason is that compression is very slow, and we re-compress the
    files again and again.
    
    Another reason is that IE/Edge doesn't work well with deflate turned on.
    Related: https://connect.microsoft.com/IE/feedbackdetail/view/950689
    The documents are not loaded at all with current code snapshot modulo
    this patch.
    
    Change-Id: I1fdd85856f448dc4ce02e1ab79e9c7474c3bb7f3

diff --git a/net/Socket.cpp b/net/Socket.cpp
index 5850e9c46..e4d2df4eb 100644
--- a/net/Socket.cpp
+++ b/net/Socket.cpp
@@ -215,7 +215,9 @@ namespace HttpHelper
         }
 
         // Disable deflate for now - until we can cache deflated data.
-        if (!deflate && true)
+        // FIXME: IE/Edge doesn't work well with deflate, so check with
+        // IE/Edge before enabling the deflate again
+        if (!deflate || true)
         {
             response.setContentLength(st.st_size);
             std::ostringstream oss;
commit 14a8797a8268abf0f31cd4efc31e99238a403cd3
Author:     Jan Holesovsky <kendy at collabora.com>
AuthorDate: Thu Apr 6 15:51:44 2017 +0200
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Thu Apr 6 15:52:57 2017 +0200

    Change the ssl termination default to 'false'.
    
    Change-Id: Iafd3f3e7ccc423fa3b04c20a141e44554df6db90

diff --git a/loolwsd.xml.in b/loolwsd.xml.in
index 20fc0dd62..a37ec2b53 100644
--- a/loolwsd.xml.in
+++ b/loolwsd.xml.in
@@ -47,7 +47,7 @@
 
     <ssl desc="SSL settings">
         <enable type="bool" default="true">true</enable>
-        <termination desc="Connection via proxy where loolwsd acts as working via https, but actually uses http." type="bool" default="true">true</termination>
+        <termination desc="Connection via proxy where loolwsd acts as working via https, but actually uses http." type="bool" default="true">false</termination>
         <cert_file_path desc="Path to the cert file" relative="false">/etc/loolwsd/cert.pem</cert_file_path>
         <key_file_path desc="Path to the key file" relative="false">/etc/loolwsd/key.pem</key_file_path>
         <ca_file_path desc="Path to the ca file" relative="false">/etc/loolwsd/ca-chain.cert.pem</ca_file_path>
commit d559471fab916377eb38fdfbc78735214df2a3b7
Author:     Pranav Kant <pranavk at collabora.co.uk>
AuthorDate: Thu Apr 6 16:59:44 2017 +0530
Commit:     Pranav Kant <pranavk at collabora.co.uk>
CommitDate: Thu Apr 6 17:02:08 2017 +0530

    loleaflet: Exit early for invalid commandvalues
    
    LO core doesn't output any change tracking information for spreadsheets
    which results in sending an empty 'commandvalues: ' message to
    loleaflet. While the actual fix for it would go in LO core, lets handle
    this empty case for now in loleaflet, so that we don't throw any runtime
    JS exceptions.
    
    Change-Id: Id2b66b8e7f1c87b074d3e72168e0ca3c3c0d345d

diff --git a/loleaflet/src/layer/tile/CalcTileLayer.js b/loleaflet/src/layer/tile/CalcTileLayer.js
index 1fa97c456..9fba31fc0 100644
--- a/loleaflet/src/layer/tile/CalcTileLayer.js
+++ b/loleaflet/src/layer/tile/CalcTileLayer.js
@@ -417,7 +417,11 @@ L.CalcTileLayer = L.TileLayer.extend({
 	},
 
 	_onCommandValuesMsg: function (textMsg) {
-		var values = JSON.parse(textMsg.substring(textMsg.indexOf('{')));
+		var jsonIdx = textMsg.indexOf('{');
+		if (jsonIdx === -1)
+			return;
+
+		var values = JSON.parse(textMsg.substring(jsonIdx));
 		if (!values) {
 			return;
 		}
commit 4538ac9ffbf163540778588995afa001f466f3e6
Author:     Jan Holesovsky <kendy at collabora.com>
AuthorDate: Thu Apr 6 10:25:19 2017 +0200
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Thu Apr 6 10:25:19 2017 +0200

    Fix comment, we run the even the loolforkit under callgrind now.
    
    Change-Id: Ic0357cb65d79af2473575a2248bfc5d86bce28ed

diff --git a/Makefile.am b/Makefile.am
index 05ea8a673..a45062405 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -248,7 +248,7 @@ run-valgrind: all @JAILS_PATH@ @SYSTEMPLATE_PATH@/system_stamp
 			  --o:logging.file[@enable]=false --o:logging.level=trace
 
 run-callgrind: all @JAILS_PATH@ @SYSTEMPLATE_PATH@/system_stamp
-	@echo "Launching loolwsd under valgrind (but not forkit/loolkit, yet)"
+	@echo "Launching loolwsd under valgrind's callgrind"
 	@fc-cache "@LO_PATH@"/share/fonts/truetype
 	@cp $(abs_top_srcdir)/test/data/hello.odt $(abs_top_srcdir)/test/data/hello-world.odt
 	valgrind --tool=callgrind --simulate-cache=yes --dump-instr=yes --num-callers=50 --error-limit=no --trace-children=yes \
commit fa042ed0e3f9a543ec075c6530ff5ce701c0be5d
Author:     Jan Holesovsky <kendy at collabora.com>
AuthorDate: Wed Apr 5 20:20:47 2017 +0200
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Thu Apr 6 10:22:38 2017 +0200

    Make the callgrinding possible again.
    
    Change-Id: I9e8e0e3d088c4af29f2701a0318a508f14327fff

diff --git a/Makefile.am b/Makefile.am
index 1f091c272..05ea8a673 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -251,8 +251,9 @@ run-callgrind: all @JAILS_PATH@ @SYSTEMPLATE_PATH@/system_stamp
 	@echo "Launching loolwsd under valgrind (but not forkit/loolkit, yet)"
 	@fc-cache "@LO_PATH@"/share/fonts/truetype
 	@cp $(abs_top_srcdir)/test/data/hello.odt $(abs_top_srcdir)/test/data/hello-world.odt
-	valgrind --tool=callgrind --simulate-cache=yes --dump-instr=yes --num-callers=50 --error-limit=no \
-		./loolwsd --o:sys_template_path="@SYSTEMPLATE_PATH@" --o:lo_template_path="@LO_PATH@" \
+	valgrind --tool=callgrind --simulate-cache=yes --dump-instr=yes --num-callers=50 --error-limit=no --trace-children=yes \
+		./loolwsd --nocaps \
+			  --o:sys_template_path="@SYSTEMPLATE_PATH@" --o:lo_template_path="@LO_PATH@" \
 			  --o:child_root_path="@JAILS_PATH@" --o:storage.filesystem[@allow]=true \
 			  --o:ssl.cert_file_path="$(abs_top_srcdir)/etc/cert.pem" \
 			  --o:ssl.key_file_path="$(abs_top_srcdir)/etc/key.pem" \
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 1b6f5d450..a5a995dfd 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -348,12 +348,6 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
     // user/doc/jailId
     const auto jailPath = Poco::Path(JAILED_DOCUMENT_ROOT, jailId);
     std::string jailRoot = getJailRoot();
-#ifndef KIT_IN_PROCESS
-    if (LOOLWSD::NoCapsForKit)
-    {
-        jailRoot = jailPath.toString() + "/" + getJailRoot();
-    }
-#endif
 
     LOG_INF("jailPath: " << jailPath.toString() << ", jailRoot: " << jailRoot);
 
diff --git a/wsd/Storage.cpp b/wsd/Storage.cpp
index 94a01c935..a125c1d75 100644
--- a/wsd/Storage.cpp
+++ b/wsd/Storage.cpp
@@ -248,7 +248,10 @@ std::string LocalStorage::loadStorageFileToLocal()
     _isLoaded = true;
     // Now return the jailed path.
 #ifndef KIT_IN_PROCESS
-    return Poco::Path(_jailPath, filename).toString();
+    if (LOOLWSD::NoCapsForKit)
+        return _jailedFilePath;
+    else
+        return Poco::Path(_jailPath, filename).toString();
 #else
     return _jailedFilePath;
 #endif
commit a4176cf2f5deed829ed4e762fddb3429c44c8c91
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Thu Apr 6 03:32:21 2017 -0400
Commit:     Ashod Nakashian <ashnakash at gmail.com>
CommitDate: Thu Apr 6 07:37:51 2017 +0000

    wsd: don't invoke poll handler when invalidated
    
    Only during shutdown do we expect a callback
    to invalidate the pollSockets, but if it happens
    we shouldn't invoke the poll handlers.
    
    Change-Id: I2f56da19aec2f04cc871bd4eae1f93da110e0eb9
    Reviewed-on: https://gerrit.libreoffice.org/36189
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/net/Socket.hpp b/net/Socket.hpp
index bb08dca1c..c726f337a 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -390,6 +390,10 @@ public:
             }
         }
 
+        // This should only happen when we're stopping.
+        if (_pollSockets.size() != size)
+            return;
+
         // Fire the poll callbacks and remove dead fds.
         std::chrono::steady_clock::time_point newNow =
             std::chrono::steady_clock::now();
commit 3d03a0fb5d9a4dcb69202816f142943578c58f8a
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Thu Apr 6 02:56:21 2017 -0400
Commit:     Ashod Nakashian <ashnakash at gmail.com>
CommitDate: Thu Apr 6 07:01:18 2017 +0000

    wsd: accomodate accept_poll shutdown
    
    When shutting down accept_poll from
    main, we can't remove sockets or cleanup.
    That work needs to be done fro within accept_poll's
    thread. This is different from when DocBroker's
    poll needs to cleanup its own sockets before
    it exists.
    
    So we split the stop and removeSockets so they
    can each be called in the proper way.
    
    For accept_poll and others that joinThread
    we queue a callback to cleanup before stopping.
    
    Change-Id: If780d6a97ac0fc6da6897f895d5b4dda443f9e73
    Reviewed-on: https://gerrit.libreoffice.org/36186
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/net/Socket.cpp b/net/Socket.cpp
index 21ab00f22..5850e9c46 100644
--- a/net/Socket.cpp
+++ b/net/Socket.cpp
@@ -96,6 +96,7 @@ void SocketPoll::startThread()
 
 void SocketPoll::joinThread()
 {
+    addCallback([this](){ removeSockets(); });
     stop();
     if (_threadStarted && _thread.joinable())
     {
diff --git a/net/Socket.hpp b/net/Socket.hpp
index cd1ea6cc4..bb08dca1c 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -264,9 +264,14 @@ public:
     /// Stop the polling thread.
     void stop()
     {
-        LOG_DBG("Stopping " << _name << " and removing all sockets.");
+        LOG_DBG("Stopping " << _name << ".");
         _stop = true;
+        wakeup();
+    }
 
+    void removeSockets()
+    {
+        LOG_DBG("Removing all sockets from " << _name << ".");
         assert(socket);
         assertCorrectThread();
 
@@ -280,8 +285,6 @@ public:
 
             _pollSockets.pop_back();
         }
-
-        wakeup();
     }
 
     bool isAlive() const { return _threadStarted && !_threadFinished; }
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 8dd3fa42d..1b6f5d450 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -266,6 +266,7 @@ void DocumentBroker::pollThread()
 
     // Stop to mark it done and cleanup.
     _poll->stop();
+    _poll->removeSockets();
 
     // Async cleanup.
     LOOLWSD::doHousekeeping();
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index ac7212945..e5d4cb689 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -2474,9 +2474,6 @@ int LOOLWSD::innerMain()
     LOG_INF("Stopping server socket listening. ShutdownFlag: " <<
             ShutdownRequestFlag << ", TerminationFlag: " << TerminationFlag);
 
-    // Disable thread checking - we'll now cleanup lots of things if we can
-    Socket::InhibitThreadChecks = true;
-
     // Wait until documents are saved and sessions closed.
     srv.stop();
 
@@ -2485,6 +2482,9 @@ int LOOLWSD::innerMain()
     for (auto& docBrokerIt : DocBrokers)
         docBrokerIt.second->joinThread();
 
+    // Disable thread checking - we'll now cleanup lots of things if we can
+    Socket::InhibitThreadChecks = true;
+
     DocBrokers.clear();
 
 #ifndef KIT_IN_PROCESS
commit a22118df104aa9ffd7834fef232a3c31ee0aeead
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Thu Apr 6 02:29:25 2017 -0400
Commit:     Ashod Nakashian <ashnakash at gmail.com>
CommitDate: Thu Apr 6 06:33:24 2017 +0000

    wsd: inhibit thread checks sooner when shutting down
    
    LOOLWSDServer::stop() now removes the accept_poll
    socket, which will assertCorrectThread. So we need
    to disable checks before it.
    
    Change-Id: I3445610c1c48c2b4c23bcfcbc87e236b36d18c0b
    Reviewed-on: https://gerrit.libreoffice.org/36185
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index e5d4cb689..ac7212945 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -2474,6 +2474,9 @@ int LOOLWSD::innerMain()
     LOG_INF("Stopping server socket listening. ShutdownFlag: " <<
             ShutdownRequestFlag << ", TerminationFlag: " << TerminationFlag);
 
+    // Disable thread checking - we'll now cleanup lots of things if we can
+    Socket::InhibitThreadChecks = true;
+
     // Wait until documents are saved and sessions closed.
     srv.stop();
 
@@ -2482,9 +2485,6 @@ int LOOLWSD::innerMain()
     for (auto& docBrokerIt : DocBrokers)
         docBrokerIt.second->joinThread();
 
-    // Disable thread checking - we'll now cleanup lots of things if we can
-    Socket::InhibitThreadChecks = true;
-
     DocBrokers.clear();
 
 #ifndef KIT_IN_PROCESS
commit 5e4528b59353733cc95b29613ba74ce2b26af0c4
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Thu Apr 6 01:59:20 2017 -0400
Commit:     Ashod Nakashian <ashnakash at gmail.com>
CommitDate: Thu Apr 6 06:20:10 2017 +0000

    wsd: leave the poll running so DocBroker can flush the sockets
    
    By stopping the poll we fail to notify the clients
    of the shutdown. Let the DocBroker poll thread
    take care of the poll stopping when it's ready.
    
    Change-Id: I2cb4c76da2722ce41a60fc1983b10dc8b18b4cab
    Reviewed-on: https://gerrit.libreoffice.org/36184
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 3ab3d121e..8dd3fa42d 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -1325,8 +1325,6 @@ void DocumentBroker::terminateChild(const std::string& closeReason, const bool r
         _childProcess->close(rude);
     }
 
-    // Stop the polling thread.
-    _poll->stop();
     _stop = true;
 }
 
commit 4a7a0fb477a376e5c281208525777c2a926f8c6a
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Thu Apr 6 01:32:39 2017 -0400
Commit:     Ashod Nakashian <ashnakash at gmail.com>
CommitDate: Thu Apr 6 06:19:06 2017 +0000

    wsd: remove sockets when stopping poll thread
    
    And assume correct thread if poll thread is
    not running (i.e. no race).
    
    Change-Id: I17958e682aba434ebb47fe0de199b9f530b54dee
    Reviewed-on: https://gerrit.libreoffice.org/36183
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/net/Socket.hpp b/net/Socket.hpp
index d1a59b22c..cd1ea6cc4 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -264,7 +264,23 @@ public:
     /// Stop the polling thread.
     void stop()
     {
+        LOG_DBG("Stopping " << _name << " and removing all sockets.");
         _stop = true;
+
+        assert(socket);
+        assertCorrectThread();
+
+        while (!_pollSockets.empty())
+        {
+            const std::shared_ptr<Socket>& socket = _pollSockets.back();
+
+            LOG_DBG("Removing socket #" << socket->getFD() << " from " << _name);
+            socket->assertCorrectThread();
+            socket->setThreadOwner(std::thread::id(0));
+
+            _pollSockets.pop_back();
+        }
+
         wakeup();
     }
 
@@ -293,7 +309,7 @@ public:
     void assertCorrectThread() const
     {
         // 0 owner means detached and can be invoked by any thread.
-        const bool sameThread = (_owner == std::thread::id(0) || std::this_thread::get_id() == _owner);
+        const bool sameThread = (!isAlive() || _owner == std::thread::id(0) || std::this_thread::get_id() == _owner);
         if (!sameThread)
             LOG_ERR("Incorrect thread affinity for " << _name << ". Expected: 0x" << std::hex <<
                     _owner << " (" << std::dec << Util::getThreadId() << ") but called from 0x" <<
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 396bf52b4..3ab3d121e 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -264,6 +264,9 @@ void DocumentBroker::pollThread()
         _poll->poll(std::min(flushTimeoutMs - elapsedMs, POLL_TIMEOUT_MS / 5));
     }
 
+    // Stop to mark it done and cleanup.
+    _poll->stop();
+
     // Async cleanup.
     LOOLWSD::doHousekeeping();
 
commit 01519eff70f1157dbbb4cb329acc7754f34a2765
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Wed Apr 5 21:31:15 2017 +0100
Commit:     Ashod Nakashian <ashnakash at gmail.com>
CommitDate: Thu Apr 6 06:16:44 2017 +0000

    Always cleanup DocBrokers in the PrisonerPoll thread.
    
    This simplifies things, and keeps process management in one thread.
    Also - wakeup the DocumentBroker when we want to stop it.
    
    Change-Id: I597ba4b34719fc072a4b4ad3697442b5eebe5784
    Reviewed-on: https://gerrit.libreoffice.org/36182
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 5a4de9e2e..396bf52b4 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -264,7 +264,7 @@ void DocumentBroker::pollThread()
         _poll->poll(std::min(flushTimeoutMs - elapsedMs, POLL_TIMEOUT_MS / 5));
     }
 
-    // Cleanup.
+    // Async cleanup.
     LOOLWSD::doHousekeeping();
 
     LOG_INF("Finished docBroker polling thread for docKey [" << _docKey << "].");
@@ -306,6 +306,12 @@ void DocumentBroker::joinThread()
     _poll->joinThread();
 }
 
+void DocumentBroker::stop()
+{
+    _stop = true;
+    _poll->wakeup();
+}
+
 bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const std::string& jailId)
 {
     assertCorrectThread();
diff --git a/wsd/DocumentBroker.hpp b/wsd/DocumentBroker.hpp
index 0af441ffc..d05437e9c 100644
--- a/wsd/DocumentBroker.hpp
+++ b/wsd/DocumentBroker.hpp
@@ -222,8 +222,7 @@ public:
     void startThread();
 
     /// Flag for termination.
-    //TODO: Take reason to broadcast to clients.
-    void stop() { _stop = true; }
+    void stop();
 
     /// Thread safe termination of this broker if it has a lingering thread
     void joinThread();
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 08a20ce7e..e5d4cb689 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -226,7 +226,7 @@ void alertAllUsersInternal(const std::string& msg)
 /// Remove dead and idle DocBrokers.
 /// The client of idle document should've greyed-out long ago.
 /// Returns true if at least one is removed.
-bool cleanupDocBrokers()
+void cleanupDocBrokers()
 {
     Util::assertIsLocked(DocBrokersMutex);
 
@@ -277,11 +277,7 @@ bool cleanupDocBrokers()
 
             LOG_END(logger);
         }
-
-        return true;
     }
-
-    return false;
 }
 
 /// Forks as many children as requested.
@@ -582,7 +578,7 @@ class PrisonerPoll : public TerminatingPoll {
 public:
     PrisonerPoll() : TerminatingPoll("prisoner_poll") {}
 
-    /// Check prisoners are still alive and balaned.
+    /// Check prisoners are still alive and balanced.
     void wakeupHook() override;
 };
 
@@ -1099,12 +1095,13 @@ bool LOOLWSD::checkAndRestoreForKit()
 #endif
 }
 
-void PrisonerPoll::wakeupHook()
+void LOOLWSD::doHousekeeping()
 {
-    LOOLWSD::doHousekeeping();
+    PrisonerPoll.wakeup();
 }
 
-void LOOLWSD::doHousekeeping()
+/// Really do the house-keeping
+void PrisonerPoll::wakeupHook()
 {
     if (!LOOLWSD::checkAndRestoreForKit())
     {
commit cbe6f0c813116b0fee78a78cee19f10a1c1b7b35
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Wed Apr 5 22:35:22 2017 -0400
Commit:     Ashod Nakashian <ashnakash at gmail.com>
CommitDate: Thu Apr 6 06:12:39 2017 +0000

    wsd: move prisoner socket in the poll thread
    
    Change-Id: I4097da97d4485d98618604c039a4570efe52bc19
    Reviewed-on: https://gerrit.libreoffice.org/36181
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/net/Socket.hpp b/net/Socket.hpp
index 6bfc63120..d1a59b22c 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -459,8 +459,8 @@ public:
         assert(it != _pollSockets.end());
 
         _pollSockets.erase(it);
-        LOG_TRC("Release socket #" << socket->getFD() << " from " << _name <<
-                " leaving " << _pollSockets.size());
+        LOG_DBG("Removing socket #" << socket->getFD() << " (of " <<
+                _pollSockets.size() << ") from " << _name);
     }
 
     size_t getSocketCount() const
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index d2506f247..08a20ce7e 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -1458,6 +1458,8 @@ private:
                 return SocketHandlerInterface::SocketOwnership::UNCHANGED;
             }
 
+            in.clear();
+
             LOG_INF("New child [" << pid << "].");
 
             UnitWSD::get().newChild(*this);
@@ -1466,15 +1468,13 @@ private:
             _childProcess = child; // weak
             addNewChild(child);
 
-            // We no longer own this thread: FIXME.
+            // We no longer own this socket.
             socket->setThreadOwner(std::thread::id(0));
 
             // Remove from prisoner poll since there is no activity
             // until we attach the childProcess (with this socket)
             // to a docBroker, which will do the polling.
-            PrisonerPoll.releaseSocket(socket);
-
-            in.clear();
+            return SocketHandlerInterface::SocketOwnership::MOVED;
         }
         catch (const std::exception& exc)
         {
@@ -1848,7 +1848,6 @@ private:
 
                     cleanupDocBrokers();
 
-                    // FIXME: What if the same document is already open? Need a fake dockey here?
                     LOG_DBG("New DocumentBroker for docKey [" << docKey << "].");
                     DocBrokers.emplace(docKey, docBroker);
                     LOG_TRC("Have " << DocBrokers.size() << " DocBrokers after inserting [" << docKey << "].");
@@ -1865,7 +1864,7 @@ private:
                         // Make sure the thread is running before adding callback.
                         docBroker->startThread();
 
-                        // We no longer own this thread: FIXME.
+                        // We no longer own this socket.
                         socket->setThreadOwner(std::thread::id(0));
 
                         docBroker->addCallback([docBroker, socket, clientSession, format]()
@@ -2094,7 +2093,7 @@ private:
                 // Make sure the thread is running before adding callback.
                 docBroker->startThread();
 
-                // We no longer own this thread: FIXME.
+                // We no longer own this socket.
                 socket->setThreadOwner(std::thread::id(0));
 
                 docBroker->addCallback([docBroker, socket, clientSession]()
commit bb4459a288fa072698a2a4d35f325d3e60c63f3c
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Wed Apr 5 21:48:35 2017 +0100
Commit:     Ashod Nakashian <ashnakash at gmail.com>
CommitDate: Thu Apr 6 06:11:35 2017 +0000

    Give up on doing thread checks during late shutdown.
    
    Change-Id: Icb600e4d734e075bec6c2cf6adbb2afd58c0d98b
    Reviewed-on: https://gerrit.libreoffice.org/36180
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 62879c1db..d2506f247 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -2485,6 +2485,10 @@ int LOOLWSD::innerMain()
     LOG_INF("Cleaning up lingering documents.");
     for (auto& docBrokerIt : DocBrokers)
         docBrokerIt.second->joinThread();
+
+    // Disable thread checking - we'll now cleanup lots of things if we can
+    Socket::InhibitThreadChecks = true;
+
     DocBrokers.clear();
 
 #ifndef KIT_IN_PROCESS
commit 737f7111b08ad4f395994769c45c69918ab0c337
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Wed Apr 5 21:01:48 2017 +0100
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Wed Apr 5 21:01:48 2017 +0100

    Set thread owner to zero earlier to avoid race.
    
    Stop-gap fix, while we come up with a nice API for transferring
    sockets between SocketPolls, and/or detaching them generally.

diff --git a/net/Socket.hpp b/net/Socket.hpp
index 6bca6abfb..6bfc63120 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -392,7 +392,6 @@ public:
             {
                 LOG_DBG("Removing socket #" << _pollFds[i].fd << " (of " <<
                         _pollSockets.size() << ") from " << _name);
-                _pollSockets[i]->setThreadOwner(std::thread::id(0));
                 _pollSockets.erase(_pollSockets.begin() + i);
             }
         }
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 408d49d45..62879c1db 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -1466,6 +1466,9 @@ private:
             _childProcess = child; // weak
             addNewChild(child);
 
+            // We no longer own this thread: FIXME.
+            socket->setThreadOwner(std::thread::id(0));
+
             // Remove from prisoner poll since there is no activity
             // until we attach the childProcess (with this socket)
             // to a docBroker, which will do the polling.
@@ -1862,6 +1865,9 @@ private:
                         // Make sure the thread is running before adding callback.
                         docBroker->startThread();
 
+                        // We no longer own this thread: FIXME.
+                        socket->setThreadOwner(std::thread::id(0));
+
                         docBroker->addCallback([docBroker, socket, clientSession, format]()
                         {
                             clientSession->setSaveAsSocket(socket);
@@ -2088,6 +2094,9 @@ private:
                 // Make sure the thread is running before adding callback.
                 docBroker->startThread();
 
+                // We no longer own this thread: FIXME.
+                socket->setThreadOwner(std::thread::id(0));
+
                 docBroker->addCallback([docBroker, socket, clientSession]()
                 {
                     // Set the ClientSession to handle Socket events.
commit 381bed9388d5cefcf3c82d349d29d0e744f73b83
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Wed Apr 5 18:06:58 2017 +0100
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Wed Apr 5 18:06:58 2017 +0100

    Remove redundant structure, include, and _stop members.

diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp
index d70d18c8b..7ad8df319 100644
--- a/wsd/ClientSession.cpp
+++ b/wsd/ClientSession.cpp
@@ -37,8 +37,7 @@ ClientSession::ClientSession(const std::string& id,
     _docBroker(docBroker),
     _uriPublic(uriPublic),
     _isDocumentOwner(false),
-    _isAttached(false),
-    _stop(false)
+    _isAttached(false)
 {
     const size_t curConnections = ++LOOLWSD::NumConnections;
     LOG_INF("ClientSession ctor [" << getName() << "], current number of connections: " << curConnections);
@@ -48,8 +47,6 @@ ClientSession::~ClientSession()
 {
     const size_t curConnections = --LOOLWSD::NumConnections;
     LOG_INF("~ClientSession dtor [" << getName() << "], current number of connections: " << curConnections);
-
-    stop();
 }
 
 SocketHandlerInterface::SocketOwnership ClientSession::handleIncomingMessage()
@@ -790,7 +787,6 @@ void ClientSession::dumpState(std::ostream& os)
     os << "\t\tisReadOnly: " << isReadOnly()
        << "\n\t\tisDocumentOwner: " << _isDocumentOwner
        << "\n\t\tisAttached: " << _isAttached
-       << "\n\t\tstop: " <<_stop
        << "\n";
     _senderQueue.dumpState(os);
 }
diff --git a/wsd/ClientSession.hpp b/wsd/ClientSession.hpp
index 3181b0c85..9cd67533a 100644
--- a/wsd/ClientSession.hpp
+++ b/wsd/ClientSession.hpp
@@ -75,13 +75,6 @@ public:
         _senderQueue.enqueue(data);
     }
 
-    bool stopping() const { return _stop || _senderQueue.stopping(); }
-    void stop()
-    {
-        _stop = true;
-        _senderQueue.stop();
-    }
-
     /// Set the save-as socket which is used to send convert-to results.
     void setSaveAsSocket(const std::shared_ptr<StreamSocket>& socket)
     {
@@ -152,7 +145,6 @@ private:
     std::unique_ptr<WopiStorage::WOPIFileInfo> _wopiFileInfo;
 
     SenderQueue<std::shared_ptr<Message>> _senderQueue;
-    std::atomic<bool> _stop;
 };
 
 #endif
diff --git a/wsd/SenderQueue.hpp b/wsd/SenderQueue.hpp
index af8199f13..41445ac98 100644
--- a/wsd/SenderQueue.hpp
+++ b/wsd/SenderQueue.hpp
@@ -26,31 +26,17 @@
 #include "Log.hpp"
 #include "TileDesc.hpp"
 
-#include "Socket.hpp" // FIXME: hack for wakeup-world ...
-
-struct SendItem
-{
-    std::shared_ptr<Message> Data;
-    std::string Meta;
-    std::chrono::steady_clock::time_point BirthTime;
-};
-
 /// A queue of data to send to certain Session's WS.
 template <typename Item>
 class SenderQueue final
 {
 public:
 
-    SenderQueue() :
-        _stop(false)
+    SenderQueue()
     {
     }
 
-    bool stopping() const { return _stop || TerminationFlag; }
-    void stop()
-    {
-        _stop = true;
-    }
+    bool stopping() const { return TerminationFlag; }
 
     size_t enqueue(const Item& item)
     {
@@ -173,7 +159,6 @@ private:
     mutable std::mutex _mutex;
     std::deque<Item> _queue;
     typedef typename std::deque<Item>::value_type queue_item_t;
-    std::atomic<bool> _stop;
 };
 
 #endif
commit 2d1764d30eb1fa5b6434291e9dde6551611de243
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Wed Apr 5 17:59:29 2017 +0100
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Wed Apr 5 17:59:29 2017 +0100

    Dump ClientSession and MessageQueue state too.

diff --git a/common/Session.cpp b/common/Session.cpp
index 9dcb5329f..69696fb3b 100644
--- a/common/Session.cpp
+++ b/common/Session.cpp
@@ -198,4 +198,26 @@ void Session::handleMessage(bool /*fin*/, WSOpCode /*code*/, std::vector<char> &
     }
 }
 
+void Session::dumpState(std::ostream& os)
+{
+    WebSocketHandler::dumpState(os);
+
+    os <<   "\t\tid: " << _id
+       << "\n\t\tname: " << _name
+       << "\n\t\tdisconnected: " << _disconnected
+       << "\n\t\tisActive: " << _isActive
+       << "\n\t\tisCloseFrame: " << _isCloseFrame
+       << "\n\t\tisReadOnly: " << _isReadOnly
+       << "\n\t\tdocURL: " << _docURL
+       << "\n\t\tjailedFilePath: " << _jailedFilePath
+       << "\n\t\tdocPwd: " << _docPassword
+       << "\n\t\thaveDocPwd: " << _haveDocPassword
+       << "\n\t\tisDocPwdProtected: " << _isDocPasswordProtected
+       << "\n\t\tDocOptions: " << _docOptions
+       << "\n\t\tuserId: " << _userId
+       << "\n\t\tuserName: " << _userName
+       << "\n\t\tlang: " << _lang
+       << "\n";
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/common/Session.hpp b/common/Session.hpp
index 2b460d432..b67466e39 100644
--- a/common/Session.hpp
+++ b/common/Session.hpp
@@ -100,6 +100,8 @@ protected:
         return std::unique_lock<std::mutex>(_mutex);
     }
 
+    void dumpState(std::ostream& os) override;
+
 private:
     virtual bool _handleInput(const char* buffer, int length) = 0;
 
diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp
index 8eca9d802..d70d18c8b 100644
--- a/wsd/ClientSession.cpp
+++ b/wsd/ClientSession.cpp
@@ -792,6 +792,7 @@ void ClientSession::dumpState(std::ostream& os)
        << "\n\t\tisAttached: " << _isAttached
        << "\n\t\tstop: " <<_stop
        << "\n";
+    _senderQueue.dumpState(os);
 }
 
 
diff --git a/wsd/SenderQueue.hpp b/wsd/SenderQueue.hpp
index 77f09770c..af8199f13 100644
--- a/wsd/SenderQueue.hpp
+++ b/wsd/SenderQueue.hpp
@@ -87,6 +87,17 @@ public:
         return _queue.size();
     }
 
+    void dumpState(std::ostream& os)
+    {
+        os << "\n\t\tqueue size " << _queue.size() << "\n";
+        std::lock_guard<std::mutex> lock(_mutex);
+        for (const Item &item : _queue)
+        {
+            os << "\t\t\ttype: " << (item->isBinary() ? "binary" : "text") << "\n";
+            os << "\t\t\t" << item->abbr() << "\n";
+        }
+    }
+
 private:
     /// Deduplicate messages based on the new one.
     /// Returns true if the new message should be
commit 185540bcde22baaaa66d530f224ffdfbc5130560
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Wed Apr 5 17:58:52 2017 +0100
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Wed Apr 5 17:58:52 2017 +0100

    Inhibit thread checks for SIGUSR1 handling.
    
    USR1 handling is not thread-safe; we walk the structures and hope.

diff --git a/net/Socket.cpp b/net/Socket.cpp
index 55bd4fb56..21ab00f22 100644
--- a/net/Socket.cpp
+++ b/net/Socket.cpp
@@ -24,6 +24,7 @@
 #include "WebSocketHandler.hpp"
 
 int SocketPoll::DefaultPollTimeoutMs = 5000;
+std::atomic<bool> Socket::InhibitThreadChecks(false);
 
 // help with initialization order
 namespace {
diff --git a/net/Socket.hpp b/net/Socket.hpp
index 3692bd109..6bca6abfb 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -44,6 +44,7 @@ class Socket
 public:
     static const int DefaultSendBufferSize = 16 * 1024;
     static const int MaximumSendBufferSize = 128 * 1024;
+    static std::atomic<bool> InhibitThreadChecks;
 
     Socket() :
         _fd(socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0)),
@@ -194,6 +195,8 @@ public:
     /// Asserts in the debug builds, otherwise just logs.
     virtual void assertCorrectThread()
     {
+        if (InhibitThreadChecks)
+            return;
         // 0 owner means detached and can be invoked by any thread.
         const bool sameThread = (_owner == std::thread::id(0) || std::this_thread::get_id() == _owner);
         if (!sameThread)
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 196a1c5d6..408d49d45 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -2192,8 +2192,11 @@ public:
 
     void dumpState(std::ostream& os)
     {
+        // FIXME: add some stop-world magic before doing the dump(?)
+        Socket::InhibitThreadChecks = true;
+
         os << "LOOLWSDServer:\n"
-           << "   Ports: server " << ClientPortNumber
+           << "  Ports: server " << ClientPortNumber
            <<          " prisoner " << MasterPortNumber << "\n"
            << "  TerminationFlag: " << TerminationFlag << "\n"
            << "  isShuttingDown: " << ShutdownRequestFlag << "\n"
@@ -2217,6 +2220,8 @@ public:
                   << "[ " << DocBrokers.size() << " ]:\n";
         for (auto &i : DocBrokers)
             i.second->dumpState(os);
+
+        Socket::InhibitThreadChecks = false;
     }
 
 private:
commit b9d1fde7465df8724805011e912c977c269a670c
Author:     Jan Holesovsky <kendy at collabora.com>
AuthorDate: Wed Apr 5 15:44:44 2017 +0200
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Wed Apr 5 15:45:39 2017 +0200

    Run fc-cache before running the unit tests too.
    
    Change-Id: I5d0cc0a1299cfdf1dc0e421d5fab8e2705a258ff

diff --git a/test/Makefile.am b/test/Makefile.am
index 2935e6a06..754f0f12c 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -69,6 +69,7 @@ endif
 
 if HAVE_LO_PATH
 check-local:
+	@fc-cache "@LO_PATH@"/share/fonts/truetype
 	./run_unit.sh --log-file test.log --trs-file test.trs
 # FIXME 2: unit-oob.la fails with symbol undefined:
 # UnitWSD::testHandleRequest(UnitWSD::TestRequest, UnitHTTPServerRequest&, UnitHTTPServerResponse&) ,
@@ -83,6 +84,7 @@ LA_LOG_DRIVER = ${top_srcdir}/test/run_unit.sh
 EXTRA_DIST = data/hello.odt data/hello.txt $(test_SOURCES) $(unittest_SOURCES) run_unit.sh
 
 check_valgrind: all
+	@fc-cache "@LO_PATH@"/share/fonts/truetype
 	./run_unit.sh --log-file test.log --trs-file test.trs --valgrind
 
 # run unittest during the normal build
@@ -90,4 +92,5 @@ all-local: unittest
 	@echo
 	@echo "Running build-time unit tests.  For more thorough testing, please run 'make check'."
 	@echo
+	@fc-cache "@LO_PATH@"/share/fonts/truetype
 	@${top_builddir}/test/unittest 2> unittest.log || { cat unittest.log ; exit 1 ; }
commit a3f93b880b5a7058b4144d6b0108bd57f29a8304
Author:     Pranav Kant <pranavk at collabora.co.uk>
AuthorDate: Wed Apr 5 19:12:26 2017 +0530
Commit:     Pranav Kant <pranavk at collabora.co.uk>
CommitDate: Wed Apr 5 19:13:21 2017 +0530

    loleaflet: Fix loop which fetches view ids from username
    
    Change-Id: Ia4fcfcb83a040369474c6962ce2c67b44f3f1cb3

diff --git a/loleaflet/src/map/Map.js b/loleaflet/src/map/Map.js
index 19b0576c2..4b7e2c396 100644
--- a/loleaflet/src/map/Map.js
+++ b/loleaflet/src/map/Map.js
@@ -149,9 +149,9 @@ L.Map = L.Evented.extend({
 	// public methods that modify map state
 
 	getViewId: function (username) {
-		for (var id in this._viewInfo) {
-			if (this._viewInfo[id].username === username) {
-				return id;
+		for (var idx in this._viewInfo) {
+			if (this._viewInfo[idx].username === username) {
+				return this._viewInfo[idx].id;
 			}
 		}
 		return -1;
commit 6e21b754ec185d076da29500f6a9211c99dd37bf
Author:     Jan Holesovsky <kendy at collabora.com>
AuthorDate: Wed Apr 5 15:38:33 2017 +0200
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Wed Apr 5 15:39:57 2017 +0200

    Run fc-cache before launching loolwsd.
    
    Otherwise the loolforkit startup can take too long with too many fonts.
    
    Change-Id: Ibbffab223a70a34bdb993e3b69a5b3d971176a93

diff --git a/Makefile.am b/Makefile.am
index c47218056..1f091c272 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -223,6 +223,7 @@ clean-local:
 
 run: all @JAILS_PATH@ @SYSTEMPLATE_PATH@/system_stamp
 	@echo "Launching loolwsd"
+	@fc-cache "@LO_PATH@"/share/fonts/truetype
 	@cp $(abs_top_srcdir)/test/data/hello.odt $(abs_top_srcdir)/test/data/hello-world.odt
 	@echo
 	./loolwsd --o:sys_template_path="@SYSTEMPLATE_PATH@" --o:lo_template_path="@LO_PATH@" \
@@ -235,6 +236,7 @@ run: all @JAILS_PATH@ @SYSTEMPLATE_PATH@/system_stamp
 
 run-valgrind: all @JAILS_PATH@ @SYSTEMPLATE_PATH@/system_stamp
 	@echo "Launching loolwsd under valgrind (but not forkit/loolkit, yet)"
+	@fc-cache "@LO_PATH@"/share/fonts/truetype
 	@cp $(abs_top_srcdir)/test/data/hello.odt $(abs_top_srcdir)/test/data/hello-world.odt
 	valgrind --tool=memcheck --trace-children=no -v --read-var-info=yes \
 		./loolwsd --o:sys_template_path="@SYSTEMPLATE_PATH@" --o:lo_template_path="@LO_PATH@" \
@@ -247,6 +249,7 @@ run-valgrind: all @JAILS_PATH@ @SYSTEMPLATE_PATH@/system_stamp
 
 run-callgrind: all @JAILS_PATH@ @SYSTEMPLATE_PATH@/system_stamp
 	@echo "Launching loolwsd under valgrind (but not forkit/loolkit, yet)"
+	@fc-cache "@LO_PATH@"/share/fonts/truetype
 	@cp $(abs_top_srcdir)/test/data/hello.odt $(abs_top_srcdir)/test/data/hello-world.odt
 	valgrind --tool=callgrind --simulate-cache=yes --dump-instr=yes --num-callers=50 --error-limit=no \
 		./loolwsd --o:sys_template_path="@SYSTEMPLATE_PATH@" --o:lo_template_path="@LO_PATH@" \
commit b6270fae57bf5f9512ea23a86c24eb9920dbe32f
Author:     Jan Holesovsky <kendy at collabora.com>
AuthorDate: Wed Apr 5 14:54:54 2017 +0200
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Wed Apr 5 14:54:54 2017 +0200

    setThreadOwner() is now needed in the release builds too.
    
    Change-Id: I1a60bcbac4251866739fee59994a202394339015

diff --git a/net/Socket.hpp b/net/Socket.hpp
index 706c8ef24..3692bd109 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -183,16 +183,12 @@ public:
     /// Set the thread-id we're bound to
     void setThreadOwner(const std::thread::id &id)
     {
-#if ENABLE_DEBUG
         if (id != _owner)
         {
             LOG_DBG("#" << _fd << " Thread affinity set to 0x" << std::hex <<
                     id << " (was 0x" << _owner << ")." << std::dec);
             _owner = id;
         }
-#else
-       (void)id;
-#endif
     }
 
     /// Asserts in the debug builds, otherwise just logs.
commit cb2b788cc77912ce943bb891eebb2299950a0fc2
Author:     Jan Holesovsky <kendy at collabora.com>
AuthorDate: Wed Apr 5 14:48:49 2017 +0200
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Wed Apr 5 14:49:30 2017 +0200

    assert(isCorrectThread()) -> assertCorrectThread().
    
    assert()'s are no-op in the release builds, but we still want to see threading
    problems in the log at least.
    
    Change-Id: Idb02bb018e8f2d628a57ab570249613ad00bcff2

diff --git a/net/Socket.hpp b/net/Socket.hpp
index a96c5c606..706c8ef24 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -195,20 +195,17 @@ public:
 #endif
     }
 
-    virtual bool isCorrectThread()
+    /// Asserts in the debug builds, otherwise just logs.
+    virtual void assertCorrectThread()
     {
-#if ENABLE_DEBUG
         // 0 owner means detached and can be invoked by any thread.
         const bool sameThread = (_owner == std::thread::id(0) || std::this_thread::get_id() == _owner);
         if (!sameThread)
-            LOG_WRN("#" << _fd << " Invoked from foreign thread. Expected: 0x" << std::hex <<
+            LOG_ERR("#" << _fd << " Invoked from foreign thread. Expected: 0x" << std::hex <<
                     _owner << " but called from 0x" << std::this_thread::get_id() << " (" <<
                     std::dec << Util::getThreadId() << ").");
 
-        return sameThread;
-#else
-        return true;
-#endif
+        assert(sameThread);
     }
 
 protected:
@@ -293,25 +290,23 @@ public:
     }
 
     /// Are we running in either shutdown, or the polling thread.
-    bool isCorrectThread() const
+    /// Asserts in the debug builds, otherwise just logs.
+    void assertCorrectThread() const
     {
-#if ENABLE_DEBUG
         // 0 owner means detached and can be invoked by any thread.
-        if (_owner != std::thread::id(0) && std::this_thread::get_id() != _owner)
-            LOG_WRN("Incorrect thread affinity for " << _name << ". Expected: 0x" << std::hex <<
+        const bool sameThread = (_owner == std::thread::id(0) || std::this_thread::get_id() == _owner);
+        if (!sameThread)
+            LOG_ERR("Incorrect thread affinity for " << _name << ". Expected: 0x" << std::hex <<
                     _owner << " (" << std::dec << Util::getThreadId() << ") but called from 0x" <<
                     std::hex << std::this_thread::get_id() << std::dec << ", stop: " << _stop);
 
-        return _stop || _owner == std::thread::id(0) || std::this_thread::get_id() == _owner;
-#else
-        return true;
-#endif
+        assert(_stop || sameThread);
     }
 
     /// Poll the sockets for available data to read or buffer to write.
     void poll(int timeoutMaxMs)
     {
-        assert(isCorrectThread());
+        assertCorrectThread();
 
         std::chrono::steady_clock::time_point now =
             std::chrono::steady_clock::now();
@@ -460,8 +455,8 @@ public:
     void releaseSocket(const std::shared_ptr<Socket>& socket)
     {
         assert(socket);
-        assert(isCorrectThread());
-        assert(socket->isCorrectThread());
+        assertCorrectThread();
+        socket->assertCorrectThread();
         auto it = std::find(_pollSockets.begin(), _pollSockets.end(), socket);
         assert(it != _pollSockets.end());
 
@@ -472,7 +467,7 @@ public:
 
     size_t getSocketCount() const
     {
-        assert(isCorrectThread());
+        assertCorrectThread();
         return _pollSockets.size();
     }
 
@@ -621,10 +616,8 @@ public:
 
         if (!_closed)
         {
-            if (isCorrectThread())
-                _socketHandler->onDisconnect();
-            else
-                LOG_WRN("#" << getFD() << " not properly shutdown. onDisconnect not called.");
+            assertCorrectThread();
+            _socketHandler->onDisconnect();
         }
 
         if (!_shutdownSignalled)
@@ -651,7 +644,7 @@ public:
                       int &timeoutMaxMs) override
     {
         // cf. SslSocket::getPollEvents
-        assert(isCorrectThread());
+        assertCorrectThread();
         int events = _socketHandler->getPollEvents(now, timeoutMaxMs);
         if (!_outBuffer.empty() || _shutdownSignalled)
             events |= POLLOUT;
@@ -661,7 +654,7 @@ public:
     /// Send data to the socket peer.
     void send(const char* data, const int len, const bool flush = true)
     {
-        assert(isCorrectThread());
+        assertCorrectThread();
         if (data != nullptr && len > 0)
         {
             _outBuffer.insert(_outBuffer.end(), data, data + len);
@@ -689,7 +682,7 @@ public:
     /// Return false iff the socket is closed.
     virtual bool readIncomingData()
     {
-        assert(isCorrectThread());
+        assertCorrectThread();
 
         // SSL decodes blocks of 16Kb, so for efficiency we use the same.
         char buf[16 * 1024];
@@ -743,7 +736,7 @@ protected:
     HandleResult handlePoll(std::chrono::steady_clock::time_point now,
                             const int events) override
     {
-        assert(isCorrectThread());
+        assertCorrectThread();
 
         _socketHandler->checkTimeout(now);
 
@@ -811,7 +804,7 @@ protected:
     /// Override to write data out to socket.
     virtual void writeOutgoingData()
     {
-        assert(isCorrectThread());
+        assertCorrectThread();
         assert(!_outBuffer.empty());
         do
         {
@@ -849,14 +842,14 @@ protected:
     /// Override to handle reading of socket data differently.
     virtual int readData(char* buf, int len)
     {
-        assert(isCorrectThread());
+        assertCorrectThread();
         return ::read(getFD(), buf, len);
     }
 
     /// Override to handle writing data to socket differently.
     virtual int writeData(const char* buf, const int len)
     {
-        assert(isCorrectThread());
+        assertCorrectThread();
         return ::write(getFD(), buf, len);
     }
 
diff --git a/net/SslSocket.hpp b/net/SslSocket.hpp
index 52292c588..2e4958836 100644
--- a/net/SslSocket.hpp
+++ b/net/SslSocket.hpp
@@ -77,7 +77,7 @@ public:
 
     bool readIncomingData() override
     {
-        assert(isCorrectThread());
+        assertCorrectThread();
 
         const int rc = doHandshake();
         if (rc <= 0)
@@ -89,7 +89,7 @@ public:
 
     void writeOutgoingData() override
     {
-        assert(isCorrectThread());
+        assertCorrectThread();
 
         const int rc = doHandshake();
         if (rc <= 0)
@@ -103,14 +103,14 @@ public:
 
     virtual int readData(char* buf, int len) override
     {
-        assert(isCorrectThread());
+        assertCorrectThread();
 
         return handleSslState(SSL_read(_ssl, buf, len));
     }
 
     virtual int writeData(const char* buf, const int len) override
     {
-        assert(isCorrectThread());
+        assertCorrectThread();
 
         assert (len > 0); // Never write 0 bytes.
         return handleSslState(SSL_write(_ssl, buf, len));
@@ -119,7 +119,7 @@ public:
     int getPollEvents(std::chrono::steady_clock::time_point now,
                       int & timeoutMaxMs) override
     {
-        assert(isCorrectThread());
+        assertCorrectThread();
         int events = _socketHandler->getPollEvents(now, timeoutMaxMs);
 
         if (_sslWantsTo == SslWantsTo::Read)
@@ -151,7 +151,7 @@ private:
 
     int doHandshake()
     {
-        assert(isCorrectThread());
+        assertCorrectThread();
 
         if (_doHandshake)
         {
@@ -179,7 +179,7 @@ private:
     /// Handles the state of SSL after read or write.
     int handleSslState(const int rc)
     {
-        assert(isCorrectThread());
+        assertCorrectThread();
 
         if (rc > 0)
         {
diff --git a/net/WebSocketHandler.hpp b/net/WebSocketHandler.hpp
index 8d689de36..66adbc0a8 100644
--- a/net/WebSocketHandler.hpp
+++ b/net/WebSocketHandler.hpp
@@ -330,7 +330,7 @@ protected:
         if (!socket || data == nullptr || len == 0)
             return -1;
 
-        assert(socket->isCorrectThread());
+        socket->assertCorrectThread();
         std::vector<char>& out = socket->_outBuffer;
 
         out.push_back(flags);
diff --git a/wsd/AdminModel.cpp b/wsd/AdminModel.cpp
index 1f3e6dcc8..a838cbf31 100644
--- a/wsd/AdminModel.cpp
+++ b/wsd/AdminModel.cpp
@@ -94,25 +94,21 @@ void Subscriber::unsubscribe(const std::string& command)
     _subscriptions.erase(command);
 }
 
-bool AdminModel::isCorrectThread() const
+void AdminModel::assertCorrectThread() const
 {
-#if ENABLE_DEBUG
     // FIXME: share this code [!]
     const bool sameThread = std::this_thread::get_id() == _owner;
     if (!sameThread)
-        LOG_WRN("Admin command invoked from foreign thread. Expected: 0x" << std::hex <<
+        LOG_ERR("Admin command invoked from foreign thread. Expected: 0x" << std::hex <<
         _owner << " but called from 0x" << std::this_thread::get_id() << " (" <<
         std::dec << Util::getThreadId() << ").");
 
-    return sameThread;
-#else
-    return true;
-#endif
+    assert(sameThread);
 }
 
 std::string AdminModel::query(const std::string& command)
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     const auto token = LOOLProtocol::getFirstToken(command);
     if (token == "documents")
@@ -150,7 +146,7 @@ std::string AdminModel::query(const std::string& command)
 /// Returns memory consumed by all active loolkit processes
 unsigned AdminModel::getKitsMemoryUsage()
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     unsigned totalMem = 0;
     unsigned docs = 0;
@@ -178,7 +174,7 @@ unsigned AdminModel::getKitsMemoryUsage()
 
 void AdminModel::subscribe(int sessionId, const std::weak_ptr<WebSocketHandler>& ws)
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     const auto ret = _subscribers.emplace(sessionId, Subscriber(sessionId, ws));
     if (!ret.second)
@@ -189,7 +185,7 @@ void AdminModel::subscribe(int sessionId, const std::weak_ptr<WebSocketHandler>&
 
 void AdminModel::subscribe(int sessionId, const std::string& command)
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     auto subscriber = _subscribers.find(sessionId);
     if (subscriber != _subscribers.end())
@@ -200,7 +196,7 @@ void AdminModel::subscribe(int sessionId, const std::string& command)
 
 void AdminModel::unsubscribe(int sessionId, const std::string& command)
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     auto subscriber = _subscribers.find(sessionId);
     if (subscriber != _subscribers.end())
@@ -209,7 +205,7 @@ void AdminModel::unsubscribe(int sessionId, const std::string& command)
 
 void AdminModel::addMemStats(unsigned memUsage)
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     _memStats.push_back(memUsage);
     if (_memStats.size() > _memStatsSize)
@@ -220,7 +216,7 @@ void AdminModel::addMemStats(unsigned memUsage)
 
 void AdminModel::addCpuStats(unsigned cpuUsage)
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     _cpuStats.push_back(cpuUsage);
     if (_cpuStats.size() > _cpuStatsSize)
@@ -231,7 +227,7 @@ void AdminModel::addCpuStats(unsigned cpuUsage)
 
 void AdminModel::setCpuStatsSize(unsigned size)
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     int wasteValuesLen = _cpuStats.size() - size;
     while (wasteValuesLen-- > 0)
@@ -245,7 +241,7 @@ void AdminModel::setCpuStatsSize(unsigned size)
 
 void AdminModel::setMemStatsSize(unsigned size)
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     int wasteValuesLen = _memStats.size() - size;
     while (wasteValuesLen-- > 0)
@@ -259,7 +255,7 @@ void AdminModel::setMemStatsSize(unsigned size)
 
 void AdminModel::notify(const std::string& message)
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     if (!_subscribers.empty())
     {
@@ -281,7 +277,7 @@ void AdminModel::notify(const std::string& message)
 void AdminModel::addDocument(const std::string& docKey, Poco::Process::PID pid,
                              const std::string& filename, const std::string& sessionId)
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     const auto ret = _documents.emplace(docKey, Document(docKey, pid, filename));
     ret.first->second.addView(sessionId);
@@ -321,7 +317,7 @@ void AdminModel::addDocument(const std::string& docKey, Poco::Process::PID pid,
 
 void AdminModel::removeDocument(const std::string& docKey, const std::string& sessionId)
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     auto docIt = _documents.find(docKey);
     if (docIt != _documents.end() && !docIt->second.isExpired())
@@ -345,7 +341,7 @@ void AdminModel::removeDocument(const std::string& docKey, const std::string& se
 
 void AdminModel::removeDocument(const std::string& docKey)
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     auto docIt = _documents.find(docKey);
     if (docIt != _documents.end())
@@ -368,7 +364,7 @@ void AdminModel::removeDocument(const std::string& docKey)
 
 std::string AdminModel::getMemStats()
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     std::ostringstream oss;
     for (const auto& i: _memStats)
@@ -381,7 +377,7 @@ std::string AdminModel::getMemStats()
 
 std::string AdminModel::getCpuStats()
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     std::ostringstream oss;
     for (const auto& i: _cpuStats)
@@ -394,7 +390,7 @@ std::string AdminModel::getCpuStats()
 
 unsigned AdminModel::getTotalActiveViews()
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     unsigned numTotalViews = 0;
     for (const auto& it: _documents)
@@ -410,7 +406,7 @@ unsigned AdminModel::getTotalActiveViews()
 
 std::string AdminModel::getDocuments() const
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     std::ostringstream oss;
     for (const auto& it: _documents)
@@ -433,7 +429,7 @@ std::string AdminModel::getDocuments() const
 
 void AdminModel::updateLastActivityTime(const std::string& docKey)
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     auto docIt = _documents.find(docKey);
     if (docIt != _documents.end())
@@ -456,7 +452,7 @@ bool Document::updateMemoryDirty(int dirty)
 
 void AdminModel::updateMemoryDirty(const std::string& docKey, int dirty)
 {
-    assert (isCorrectThread());
+    assertCorrectThread();
 
     auto docIt = _documents.find(docKey);
     if (docIt != _documents.end() &&
diff --git a/wsd/AdminModel.hpp b/wsd/AdminModel.hpp
index 57bd702b1..9a7ee8c9b 100644
--- a/wsd/AdminModel.hpp
+++ b/wsd/AdminModel.hpp
@@ -153,7 +153,8 @@ public:
     void setThreadOwner(const std::thread::id &id) { _owner = id; }
 
     /// In debug mode check that code is running in the correct thread.
-    bool isCorrectThread() const;
+    /// Asserts in the debug builds, otherwise just logs.
+    void assertCorrectThread() const;
 
     std::string query(const std::string& command);
 
diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp
index af5a653bf..8eca9d802 100644
--- a/wsd/ClientSession.cpp
+++ b/wsd/ClientSession.cpp
@@ -730,7 +730,7 @@ void ClientSession::onDisconnect()
 
     const auto docBroker = getDocumentBroker();
     LOG_CHECK_RET(docBroker && "Null DocumentBroker instance", );
-    assert(docBroker->isCorrectThread());
+    docBroker->assertCorrectThread();
     const auto docKey = docBroker->getDocKey();
 
     try
diff --git a/wsd/ClientSession.hpp b/wsd/ClientSession.hpp
index f3cecee9d..3181b0c85 100644
--- a/wsd/ClientSession.hpp
+++ b/wsd/ClientSession.hpp
@@ -68,7 +68,8 @@ public:
     {
         const auto docBroker = _docBroker.lock();
         // If in the correct thread - no need for wakeups.
-        assert (!docBroker || docBroker->isCorrectThread());
+        if (docBroker)
+            docBroker->assertCorrectThread();
 
         LOG_TRC(getName() << " enqueueing client message " << data->id());
         _senderQueue.enqueue(data);
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index cafbd4248..5a4de9e2e 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -172,9 +172,9 @@ void DocumentBroker::startThread()
     _poll->startThread();
 }
 
-bool DocumentBroker::isCorrectThread()
+void DocumentBroker::assertCorrectThread()
 {
-    return _poll->isCorrectThread();
+    _poll->assertCorrectThread();
 }
 
 // The inner heart of the DocumentBroker - our poll loop.
@@ -281,7 +281,7 @@ bool DocumentBroker::isAlive() const
 
 DocumentBroker::~DocumentBroker()
 {
-    assert(isCorrectThread());
+    assertCorrectThread();
 
     Admin::instance().rmDoc(_docKey);
 
@@ -308,7 +308,7 @@ void DocumentBroker::joinThread()
 
 bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const std::string& jailId)
 {
-    assert(isCorrectThread());
+    assertCorrectThread();
 
     const std::string sessionId = session->getId();
 
@@ -503,7 +503,7 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
 bool DocumentBroker::saveToStorage(const std::string& sessionId,
                                    bool success, const std::string& result)
 {
-    assert(isCorrectThread());
+    assertCorrectThread();
 
     const bool res = saveToStorageInternal(sessionId, success, result);
 
@@ -527,7 +527,7 @@ bool DocumentBroker::saveToStorage(const std::string& sessionId,
 bool DocumentBroker::saveToStorageInternal(const std::string& sessionId,
                                            bool success, const std::string& result)
 {
-    assert(isCorrectThread());
+    assertCorrectThread();
 
     // If save requested, but core didn't save because document was unmodified
     // notify the waiting thread, if any.
@@ -636,7 +636,7 @@ void DocumentBroker::setLoaded()
 
 bool DocumentBroker::autoSave(const bool force)
 {
-    assert(isCorrectThread());
+    assertCorrectThread();
 
     if (_sessions.empty() || _storage == nullptr || !_isLoaded ||
         !_childProcess->isAlive() || (!_isModified && !force))
@@ -677,7 +677,7 @@ bool DocumentBroker::autoSave(const bool force)
 
 bool DocumentBroker::sendUnoSave(const bool dontSaveIfUnmodified)
 {
-    assert(isCorrectThread());
+    assertCorrectThread();
 
     LOG_INF("Autosave triggered for doc [" << _docKey << "].");
 
@@ -750,7 +750,7 @@ std::string DocumentBroker::getJailRoot() const
 
 size_t DocumentBroker::addSession(const std::shared_ptr<ClientSession>& session)
 {
-    assert(isCorrectThread());
+    assertCorrectThread();
 
     try
     {
@@ -803,7 +803,7 @@ size_t DocumentBroker::addSession(const std::shared_ptr<ClientSession>& session)
 
 size_t DocumentBroker::removeSession(const std::string& id, bool destroyIfLast)
 {
-    assert(isCorrectThread());
+    assertCorrectThread();
 
     if (destroyIfLast)
         destroyIfLastEditor(id);
@@ -826,7 +826,7 @@ size_t DocumentBroker::removeSession(const std::string& id, bool destroyIfLast)
 
 size_t DocumentBroker::removeSessionInternal(const std::string& id)
 {
-    assert(isCorrectThread());
+    assertCorrectThread();
     try
     {
         Admin::instance().rmDoc(_docKey, id);
@@ -880,7 +880,7 @@ void DocumentBroker::addSocketToPoll(const std::shared_ptr<Socket>& socket)
 
 void DocumentBroker::alertAllUsers(const std::string& msg)
 {
-    assert(isCorrectThread());
+    assertCorrectThread();
 
     auto payload = std::make_shared<Message>(msg, Message::Dir::Out);
 
@@ -952,7 +952,7 @@ void DocumentBroker::invalidateTiles(const std::string& tiles)
 void DocumentBroker::handleTileRequest(TileDesc& tile,
                                        const std::shared_ptr<ClientSession>& session)
 {
-    assert(isCorrectThread());
+    assertCorrectThread();
     std::unique_lock<std::mutex> lock(_mutex);
 
     tile.setVersion(++_tileVersion);
@@ -1142,7 +1142,7 @@ void DocumentBroker::handleTileCombinedResponse(const std::vector<char>& payload
 
 void DocumentBroker::destroyIfLastEditor(const std::string& id)
 {
-    assert(isCorrectThread());
+    assertCorrectThread();
 
     const auto currentSession = _sessions.find(id);
     if (currentSession == _sessions.end())
@@ -1182,7 +1182,7 @@ void DocumentBroker::setModified(const bool value)
 
 bool DocumentBroker::forwardToChild(const std::string& viewId, const std::string& message)
 {
-    assert(isCorrectThread());
+    assertCorrectThread();
 
     LOG_TRC("Forwarding payload to child [" << viewId << "]: " << message);
 
@@ -1214,7 +1214,7 @@ bool DocumentBroker::forwardToChild(const std::string& viewId, const std::string
 
 bool DocumentBroker::forwardToClient(const std::shared_ptr<Message>& payload)
 {
-    assert(isCorrectThread());
+    assertCorrectThread();
 
     const std::string& msg = payload->abbr();
     const std::string& prefix = payload->forwardToken();
@@ -1258,7 +1258,7 @@ bool DocumentBroker::forwardToClient(const std::shared_ptr<Message>& payload)
 
 void DocumentBroker::childSocketTerminated()
 {
-    assert(isCorrectThread());
+    assertCorrectThread();
 
     if (!_childProcess->isAlive())
     {
@@ -1282,7 +1282,7 @@ void DocumentBroker::childSocketTerminated()
 
 void DocumentBroker::terminateChild(const std::string& closeReason, const bool rude)
 {
-    assert(isCorrectThread());
+    assertCorrectThread();
 
     LOG_INF("Terminating doc [" << _docKey << "].");
 
@@ -1323,7 +1323,7 @@ void DocumentBroker::terminateChild(const std::string& closeReason, const bool r
 
 void DocumentBroker::closeDocument(const std::string& reason)
 {
-    assert(isCorrectThread());
+    assertCorrectThread();
 
     LOG_DBG("Closing DocumentBroker for docKey [" << _docKey << "] with reason: " << reason);
     terminateChild(reason, true);
diff --git a/wsd/DocumentBroker.hpp b/wsd/DocumentBroker.hpp
index 168734cc7..0af441ffc 100644
--- a/wsd/DocumentBroker.hpp
+++ b/wsd/DocumentBroker.hpp
@@ -259,7 +259,8 @@ public:
     }
 
     /// Are we running in either shutdown, or the polling thread.
-    bool isCorrectThread();
+    /// Asserts in the debug builds, otherwise just logs.
+    void assertCorrectThread();
 
     /// Pretty print internal state to a stream.
     void dumpState(std::ostream& os);
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 763faa1ce..196a1c5d6 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -1374,7 +1374,7 @@ private:
         if (docBroker)
         {
             auto lock = docBroker->getLock();
-            assert(docBroker->isCorrectThread());
+            docBroker->assertCorrectThread();
             docBroker->stop();
         }
     }
diff --git a/wsd/TestStubs.cpp b/wsd/TestStubs.cpp
index 7972aec5c..b9ff5a582 100644
--- a/wsd/TestStubs.cpp
+++ b/wsd/TestStubs.cpp
@@ -15,6 +15,6 @@
 
 #include "DocumentBroker.hpp"
 
-bool DocumentBroker::isCorrectThread() { return true; }
+void DocumentBroker::assertCorrectThread() {}
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit a411e5b4c2dfe6d37f525fc43e04268bd74f7759
Author:     Pranav Kant <pranavk at collabora.co.uk>
AuthorDate: Wed Apr 5 17:17:32 2017 +0530
Commit:     Pranav Kant <pranavk at collabora.co.uk>
CommitDate: Wed Apr 5 17:17:32 2017 +0530

    Fix cannot paste into the document
    
    Change-Id: I14eac943ee1b6ef83e2ea1707e34218bd85b4b13

diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js
index a5ea4bcdf..dd2331d61 100644
--- a/loleaflet/src/layer/tile/TileLayer.js
+++ b/loleaflet/src/layer/tile/TileLayer.js
@@ -1741,7 +1741,7 @@ L.TileLayer = L.GridLayer.extend({
 		e = e.originalEvent;
 		e.preventDefault();
 		var pasteString = L.Compatibility.clipboardGet(e);
-		if (pasteString === 'false' || !!pasteString || pasteString === this._selectionTextHash) {
+		if (pasteString === 'false' || !pasteString || pasteString === this._selectionTextHash) {
 			// If there is nothing to paste in clipboard, no harm in
 			// issuing a .uno:Paste in case there is something internally copied in the document
 			// or if the content of the clipboard did not change, we surely must do a rich paste
commit 4b7dee56528650e72bbef5bbc06c647c3a79e653
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Wed Apr 5 11:57:11 2017 +0100
Commit:     Michael Meeks <michael.meeks at collabora.com>
CommitDate: Wed Apr 5 11:57:11 2017 +0100

    Remove un-used _stop member, and cleanup redundant code.

diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index e05206c6f..763faa1ce 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -2156,7 +2156,6 @@ class LOOLWSDServer
     const LOOLWSDServer& operator=(LOOLWSDServer&& other) = delete;
 public:
     LOOLWSDServer() :
-        _stop(false),
         _acceptPoll("accept_poll")
     {
     }
@@ -2174,7 +2173,6 @@ public:
 
     void stopPrisoners()
     {
-        PrisonerPoll.stop();
         PrisonerPoll.joinThread();
     }
 
@@ -2188,10 +2186,6 @@ public:
 
     void stop()
     {
-        _stop = true;
-        _acceptPoll.stop();
-        WebServerPoll.stop();
-        SocketPoll::wakeupWorld(); //TODO: Why?
         _acceptPoll.joinThread();
         WebServerPoll.joinThread();
     }
@@ -2201,7 +2195,6 @@ public:
         os << "LOOLWSDServer:\n"
            << "   Ports: server " << ClientPortNumber
            <<          " prisoner " << MasterPortNumber << "\n"
-           << "  stop: " << _stop << "\n"
            << "  TerminationFlag: " << TerminationFlag << "\n"
            << "  isShuttingDown: " << ShutdownRequestFlag << "\n"
            << "  NewChildren: " << NewChildren.size() << "\n"
@@ -2227,8 +2220,6 @@ public:
     }
 
 private:
-    std::atomic<bool> _stop;
-
     class AcceptPoll : public TerminatingPoll {
     public:
         AcceptPoll(const std::string &threadName) :
commit 37387518f43f895bde0db877ca4d5fe94c0d28e6
Author:     Jan Holesovsky <kendy at collabora.com>
AuthorDate: Wed Apr 5 11:57:28 2017 +0200
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Wed Apr 5 12:03:33 2017 +0200

    Suppress assert()'s in the production builds.
    
    Change-Id: I2074ed335b7201337e6519440ff6bed1809be915

diff --git a/Makefile.am b/Makefile.am
index 3f45901ee..c47218056 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -27,6 +27,10 @@ AM_CPPFLAGS = -pthread -DLOOLWSD_DATADIR='"@LOOLWSD_DATADIR@"' \
 	      -DDEBUG_ABSSRCDIR='"@abs_srcdir@"' \
 	      ${include_paths}
 
+if !ENABLE_DEBUG
+AM_CPPFLAGS += -DNDEBUG
+endif
+
 AM_LDFLAGS = -pthread -Wl,-E,-rpath,/snap/loolwsd/current/usr/lib $(ZLIB_LIBS)
 
 if ENABLE_SSL
diff --git a/common/Util.hpp b/common/Util.hpp
index b0e29024b..63bffc975 100644
--- a/common/Util.hpp
+++ b/common/Util.hpp
@@ -77,12 +77,20 @@ namespace Util
     template <typename T>
     void assertIsLocked(const T& lock)
     {
+#ifdef NDEBUG
+        (void) lock;
+#else
         assert(lock.owns_lock());
+#endif
     }
 
     inline void assertIsLocked(std::mutex& mtx)
     {
+#ifdef NDEBUG
+        (void) mtx;
+#else
         assert(!mtx.try_lock());
+#endif
     }
 
     /// Returns the process PSS in KB (works only when we have perms for /proc/pid/smaps).
diff --git a/configure.ac b/configure.ac
index f52906742..74d56bd9c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -246,6 +246,7 @@ AS_IF([test "$enable_ssl" != "no"],
       [AC_DEFINE([ENABLE_SSL],0,[Whether to enable SSL])])
 
 AM_CONDITIONAL([ENABLE_SSL], [test "$enable_ssl" != "no"])
+AM_CONDITIONAL([ENABLE_DEBUG], [test "$ENABLE_DEBUG" = "true"])
 
 ENABLE_SSL=
 if test "$enable_ssl" != "no"; then
diff --git a/net/clientnb.cpp b/net/clientnb.cpp
index 311491e6b..d7b75e211 100644
--- a/net/clientnb.cpp
+++ b/net/clientnb.cpp
@@ -144,7 +144,10 @@ struct ThreadWorker : public Runnable
         {
             Session ping(_domain ? _domain : "init", EnableHttps);
             ping.sendPing(i);
-            int back = ping.getResponseInt();
+#ifndef NDEBUG
+            int back =
+#endif
+                ping.getResponseInt();
             assert(back == i + 1);
         }
     }
@@ -209,7 +212,10 @@ struct Client : public Poco::Util::Application
             ws->sendFrame(&i, sizeof(i), WebSocket::SendFlags::FRAME_BINARY);
             size_t back[5];
             int flags = 0;
-            int recvd = ws->receiveFrame((void *)back, sizeof(back), flags);
+#ifndef NDEBUG
+            int recvd =
+#endif
+                ws->receiveFrame((void *)back, sizeof(back), flags);
             assert(recvd == sizeof(size_t));
             assert(back[0] == i + 1);
         }
@@ -233,7 +239,10 @@ struct Client : public Poco::Util::Application
 
             res.resize(i);
             int flags;
-            int recvd = ws->receiveFrame(res.data(), res.size(), flags);
+#ifndef NDEBUG
+            int recvd =
+#endif
+                ws->receiveFrame(res.data(), res.size(), flags);
             assert(recvd == static_cast<int>(i));
 
             if (i == sizeof(size_t))
commit d345c29a477bf7edd98b7b884aaacc4c06b82869
Author:     Jan Holesovsky <kendy at collabora.com>
AuthorDate: Wed Apr 5 11:35:59 2017 +0200
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Wed Apr 5 11:38:48 2017 +0200

    The other isCorrectThread() should be active only in the debug build too.
    
    Change-Id: Ieadb7e14f70752f5cfb2fd9ee569b56fb39d528b

diff --git a/net/Socket.hpp b/net/Socket.hpp
index 4fa51dce0..a96c5c606 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -295,6 +295,7 @@ public:
     /// Are we running in either shutdown, or the polling thread.
     bool isCorrectThread() const
     {
+#if ENABLE_DEBUG
         // 0 owner means detached and can be invoked by any thread.
         if (_owner != std::thread::id(0) && std::this_thread::get_id() != _owner)
             LOG_WRN("Incorrect thread affinity for " << _name << ". Expected: 0x" << std::hex <<
@@ -302,6 +303,9 @@ public:
                     std::hex << std::this_thread::get_id() << std::dec << ", stop: " << _stop);
 
         return _stop || _owner == std::thread::id(0) || std::this_thread::get_id() == _owner;
+#else
+        return true;
+#endif
     }
 
     /// Poll the sockets for available data to read or buffer to write.
commit 1ad4037dd78b8e319d3615c00010bbdf2b76cf35
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Wed Apr 5 00:36:33 2017 -0400
Commit:     Ashod Nakashian <ashnakash at gmail.com>
CommitDate: Wed Apr 5 04:48:00 2017 +0000

    wsd: allow for slow startup of LOK
    
    Change-Id: Idf821f2a3638e76e1a8b169d5672a2059b00491c
    Reviewed-on: https://gerrit.libreoffice.org/36118
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/test/run_unit.sh.in b/test/run_unit.sh.in
index dc1d4021e..4b8e71cfa 100755
--- a/test/run_unit.sh.in
+++ b/test/run_unit.sh.in
@@ -75,13 +75,14 @@ if test "z$tst" == "z"; then
                                  --o:child_root_path="$jails_path" \
                                  --o:storage.filesystem[@allow]=true \
                                  --o:logging.level=trace \
-	                         --o:logging.file[@enable]=false \
+                                 --o:logging.file[@enable]=false \
                                  --o:ssl.key_file_path="${abs_top_builddir}/etc/key.pem" \
                                  --o:ssl.cert_file_path="${abs_top_builddir}/etc/cert.pem" \
                                  --o:ssl.ca_file_path="${abs_top_builddir}/etc/ca-chain.cert.pem" \
                                  --o:admin_console.username=admin --o:admin_console.password=admin \
                                  > "$tst_log" 2>&1 &
      echo "  executing test"
+     sleep 5 # allow for wsd to startup
 
      oldpath=`pwd`
      cd "${abs_top_builddir}/test"
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index f2f6d0dfc..e05206c6f 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -2410,7 +2410,7 @@ int LOOLWSD::innerMain()
     {
         std::unique_lock<std::mutex> lock(NewChildrenMutex);
 
-        const auto timeoutMs = CHILD_TIMEOUT_MS * (LOOLWSD::NoCapsForKit ? 150 : 3);
+        const auto timeoutMs = CHILD_TIMEOUT_MS * (LOOLWSD::NoCapsForKit ? 150 : 10);
         const auto timeout = std::chrono::milliseconds(timeoutMs);
         // Make sure we have at least one before moving forward.
         LOG_TRC("Waiting for a new child for a max of " << timeoutMs << " ms.");
commit 463f26f417958d55270118f3aeac279ce689f2bc
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Wed Apr 5 00:26:31 2017 -0400
Commit:     Ashod Nakashian <ashnakash at gmail.com>
CommitDate: Wed Apr 5 04:47:30 2017 +0000

    wsd: mark detached sockets to have no owner
    
    The DocBroker might not get a chance to
    take ownership of a socket (which is done
    via callbacks that are invoked in the poll loop)
    if it (or WSD) is flagged for termination.
    
    In that case, DocBroker doesn't take ownership
    but ultimately needs to disconnect the socket.
    
    By detaching ownership we signal that any thread
    can rightly take ownership and thus avoid spurious
    warning or assertions.
    
    Change-Id: Idb192bfaac05c5c86809cb21876f3926a080b775
    Reviewed-on: https://gerrit.libreoffice.org/36117
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/net/Socket.hpp b/net/Socket.hpp
index f0a9975c9..4fa51dce0 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -198,7 +198,8 @@ public:
     virtual bool isCorrectThread()
     {
 #if ENABLE_DEBUG
-        const bool sameThread = std::this_thread::get_id() == _owner;
+        // 0 owner means detached and can be invoked by any thread.
+        const bool sameThread = (_owner == std::thread::id(0) || std::this_thread::get_id() == _owner);
         if (!sameThread)
             LOG_WRN("#" << _fd << " Invoked from foreign thread. Expected: 0x" << std::hex <<
                     _owner << " but called from 0x" << std::this_thread::get_id() << " (" <<
@@ -294,12 +295,13 @@ public:
     /// Are we running in either shutdown, or the polling thread.
     bool isCorrectThread() const
     {
-        if (std::this_thread::get_id() != _owner)
+        // 0 owner means detached and can be invoked by any thread.
+        if (_owner != std::thread::id(0) && std::this_thread::get_id() != _owner)
             LOG_WRN("Incorrect thread affinity for " << _name << ". Expected: 0x" << std::hex <<
                     _owner << " (" << std::dec << Util::getThreadId() << ") but called from 0x" <<
                     std::hex << std::this_thread::get_id() << std::dec << ", stop: " << _stop);
 
-        return _stop || std::this_thread::get_id() == _owner;
+        return _stop || _owner == std::thread::id(0) || std::this_thread::get_id() == _owner;
     }
 
     /// Poll the sockets for available data to read or buffer to write.
@@ -392,6 +394,7 @@ public:
             {
                 LOG_DBG("Removing socket #" << _pollFds[i].fd << " (of " <<
                         _pollSockets.size() << ") from " << _name);
+                _pollSockets[i]->setThreadOwner(std::thread::id(0));
                 _pollSockets.erase(_pollSockets.begin() + i);
             }
         }
commit 2254b71682a7314c1113ce4aa521de786d1d69c1
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Wed Apr 5 00:26:09 2017 -0400
Commit:     Ashod Nakashian <ashnakash at gmail.com>
CommitDate: Wed Apr 5 04:46:52 2017 +0000

    wsd: some informative logging
    
    Change-Id: I4338f5bd8056d1d66da01efaa1a1fe54f8717793
    Reviewed-on: https://gerrit.libreoffice.org/36116
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 97626af93..cafbd4248 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -243,6 +243,10 @@ void DocumentBroker::pollThread()
         }
     }
 
+    LOG_INF("Finished polling doc [" << _docKey << "]. stop: " << _stop << ", continuePolling: " <<
+            _poll->continuePolling() << ", TerminationFlag: " << TerminationFlag <<
+            ", ShutdownRequestFlag: " << ShutdownRequestFlag << ".");
+
     // Terminate properly while we can.
     //TODO: pass some sensible reason.
     terminateChild("", false);
@@ -839,6 +843,10 @@ size_t DocumentBroker::removeSessionInternal(const std::string& id)
             LOG_TRC("Removed " << (readonly ? "readonly" : "non-readonly") <<
                     " session [" << id << "] from docKey [" <<
                     _docKey << "] to have " << count << " sessions.");
+            for (const auto& pair : _sessions)
+            {
+                LOG_TRC("Session: " << pair.second->getName());
+            }
 
             // Let the child know the client has disconnected.
             const std::string msg("child-" + id + " disconnect");
diff --git a/wsd/TileCache.cpp b/wsd/TileCache.cpp
index 4c1d75724..b744eded5 100644
--- a/wsd/TileCache.cpp
+++ b/wsd/TileCache.cpp
@@ -53,7 +53,8 @@ TileCache::TileCache(const std::string& docURL,
     _cacheDir(cacheDir)
 {
     LOG_INF("TileCache ctor for uri [" << _docURL <<
-            "] modifiedTime=" << (modifiedTime.raw()/1000000) <<
+            "], cacheDir: [" << _cacheDir <<
+            "], modifiedTime=" << (modifiedTime.raw()/1000000) <<
             " getLastModified()=" << (getLastModified().raw()/1000000));
     File directory(_cacheDir);
     std::string unsaved;
commit 38f955b5c54ada780afec69ed16e286989c1c17e
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Wed Apr 5 00:25:15 2017 -0400
Commit:     Ashod Nakashian <ashnakash at gmail.com>
CommitDate: Wed Apr 5 04:46:22 2017 +0000

    wsd: start DocBroker thread before adding callbacks
    
    And move more into the callback to ensure
    thread affinity.
    
    Change-Id: I1d6985716d0d36aa488b65263ecb41f444f77255
    Reviewed-on: https://gerrit.libreoffice.org/36115
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 367395cfd..f2f6d0dfc 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -1856,15 +1856,19 @@ private:
                     auto clientSession = createNewClientSession(nullptr, _id, uriPublic, docBroker, isReadOnly);
                     if (clientSession)
                     {
-                        clientSession->setSaveAsSocket(socket);
-
                         // Transfer the client socket to the DocumentBroker.
-                        // Move the socket into DocBroker.
-                        docBroker->addSocketToPoll(socket);
                         socketOwnership = SocketHandlerInterface::SocketOwnership::MOVED;
 
-                        docBroker->addCallback([&, clientSession]()
+                        // Make sure the thread is running before adding callback.
+                        docBroker->startThread();
+
+                        docBroker->addCallback([docBroker, socket, clientSession, format]()
                         {
+                            clientSession->setSaveAsSocket(socket);
+
+                            // Move the socket into DocBroker.
+                            docBroker->addSocketToPoll(socket);
+
                             // First add and load the session.
                             docBroker->addSession(clientSession);
 
@@ -1888,8 +1892,6 @@ private:
                             clientSession->handleMessage(true, WebSocketHandler::WSOpCode::Text, saveasRequest);
                         });
 
-                        docBroker->startThread();
-
                         sent = true;
                     }
                     else
@@ -2083,6 +2085,9 @@ private:
                 // Remove from current poll as we're moving ownership.
                 socketOwnership = SocketHandlerInterface::SocketOwnership::MOVED;
 
+                // Make sure the thread is running before adding callback.
+                docBroker->startThread();
+
                 docBroker->addCallback([docBroker, socket, clientSession]()
                 {
                     // Set the ClientSession to handle Socket events.
@@ -2095,8 +2100,6 @@ private:
                     // Add and load the session.
                     docBroker->addSession(clientSession);
                 });
-
-                docBroker->startThread();
             }
             else
             {
commit 2576f9c4e9dc8a4e7eb084b4bc74055f0c92e850
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Wed Apr 5 00:21:49 2017 -0400
Commit:     Ashod Nakashian <ashnakash at gmail.com>
CommitDate: Wed Apr 5 04:45:49 2017 +0000

    wsd: correctly search for available prisoner port
    
    Search for the next 100 ports for a usable one
    and pass the one found to forkit so it connects
    on that one instead of the default.
    
    Change-Id: I26697dd8b5a35992f9e000a35ad5b44c3a3699dd
    Reviewed-on: https://gerrit.libreoffice.org/36114
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index c861fe61c..367395cfd 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -2163,7 +2163,7 @@ public:
         stop();
     }
 
-    void startPrisoners(const int port)
+    void startPrisoners(int& port)
     {
         PrisonerPoll.startThread();
         PrisonerPoll.insertNewSocket(findPrisonerServerPort(port));
@@ -2253,31 +2253,27 @@ private:
 
         if (!serverSocket->bind(addr))
         {
-            LOG_ERR("Failed to bind to: " << addr.toString());
+            LOG_SYS("Failed to bind to: " << addr.toString());
             return nullptr;
         }
 
         if (serverSocket->listen())
             return serverSocket;
 
-        LOG_ERR("Failed to listen on: " << addr.toString());
+        LOG_SYS("Failed to listen on: " << addr.toString());
         return nullptr;
     }
 
-    std::shared_ptr<ServerSocket> findPrisonerServerPort(int port)
+    std::shared_ptr<ServerSocket> findPrisonerServerPort(int& port)
     {
         std::shared_ptr<SocketFactory> factory = std::make_shared<PrisonerSocketFactory>();
+
+        LOG_INF("Trying to listen on prisoner port " << port << ".");
         std::shared_ptr<ServerSocket> socket = getServerSocket(SocketAddress("127.0.0.1", port),
                                                                PrisonerPoll, factory);
 
-        if (!UnitWSD::isUnitTesting() && !socket)
-        {
-            LOG_FTL("Failed to listen on Prisoner master port (" <<
-                    MasterPortNumber << "). Exiting.");
-            _exit(Application::EXIT_SOFTWARE);
-        }
-
-        while (!socket)
+        // If we fail, try the next 100 ports.
+        for (int i = 0; i < 100 && !socket; ++i)
         {
             ++port;
             LOG_INF("Prisoner port " << (port - 1) << " is busy, trying " << port << ".");
@@ -2285,6 +2281,14 @@ private:
                                      PrisonerPoll, factory);
         }
 
+        if (!UnitWSD::isUnitTesting() && !socket)
+        {
+            LOG_FTL("Failed to listen on Prisoner port (" <<
+                    MasterPortNumber << '-' << port << "). Exiting.");
+            _exit(Application::EXIT_SOFTWARE);
+        }
+
+        LOG_INF("Listening to prisoner connections on port " << port);
         return socket;
     }
 
commit e848996247c4b7baf1241e79c09835a844b719ec
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Wed Apr 5 00:18:16 2017 -0400
Commit:     Ashod Nakashian <ashnakash at gmail.com>
CommitDate: Wed Apr 5 04:45:23 2017 +0000

    wsd: simplify career span timing
    
    Change-Id: I0bfb3bca99f3f20ca9244e580c80801e89890fc2
    Reviewed-on: https://gerrit.libreoffice.org/36113
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index b8d943bef..c861fe61c 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -182,7 +182,7 @@ static std::mutex DocBrokersMutex;
 extern "C" { void dump_state(void); /* easy for gdb */ }
 
 #if ENABLE_DEBUG
-static int careerSpanSeconds = 0;
+static int careerSpanMs = 0;
 #endif
 
 namespace
@@ -985,7 +985,7 @@ void LOOLWSD::handleOption(const std::string& optionName,
         NoCapsForKit = true;
 #endif
     else if (optionName == "careerspan")
-        careerSpanSeconds = std::stoi(value);
+        careerSpanMs = std::stoi(value) * 1000; // Convert second to ms
 
     static const char* clientPort = std::getenv("LOOL_TEST_CLIENT_PORT");
     if (clientPort)
@@ -2427,14 +2427,11 @@ int LOOLWSD::innerMain()
     // Start the server.
     srv.start(ClientPortNumber);
 
-#if ENABLE_DEBUG
-    time_t startTimeSpan = time(nullptr);
-#endif
-
-    auto startStamp = std::chrono::steady_clock::now();
-
     /// The main-poll does next to nothing:
     SocketPoll mainWait("main");
+
+    const auto startStamp = std::chrono::steady_clock::now();
+
     while (!TerminationFlag && !ShutdownRequestFlag)
     {
         UnitWSD::get().invokeTest();
@@ -2448,16 +2445,17 @@ int LOOLWSD::innerMain()
         // Wake the prisoner poll to spawn some children, if necessary.
         PrisonerPoll.wakeup();
 
+        const auto timeSinceStartMs = std::chrono::duration_cast<std::chrono::milliseconds>(
+                                            std::chrono::steady_clock::now() - startStamp).count();
+
         // Unit test timeout
-        if (std::chrono::duration_cast<std::chrono::milliseconds>(
-                std::chrono::steady_clock::now() - startStamp).count() >
-            UnitWSD::get().getTimeoutMilliSeconds())
+        if (timeSinceStartMs > UnitWSD::get().getTimeoutMilliSeconds())
             UnitWSD::get().timeout();
 
 #if ENABLE_DEBUG
-        if (careerSpanSeconds > 0 && time(nullptr) > startTimeSpan + careerSpanSeconds)
+        if (careerSpanMs > 0 && timeSinceStartMs > careerSpanMs)
         {
-            LOG_INF((time(nullptr) - startTimeSpan) << " seconds gone, finishing as requested.");
+            LOG_INF(timeSinceStartMs << " milliseconds gone, finishing as requested.");
             break;
         }
 #endif
commit fa753e5e0657b230526e71477a9fcdb16f91f4a6
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Tue Apr 4 21:30:29 2017 -0400
Commit:     Ashod Nakashian <ashnakash at gmail.com>
CommitDate: Wed Apr 5 04:45:03 2017 +0000

    wsd: time lok_preinit and log when finished
    
    Change-Id: I2ea3dc226c84870690bbf9b041263650c923d5bd
    Reviewed-on: https://gerrit.libreoffice.org/36112
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/kit/Kit.cpp b/kit/Kit.cpp
index 40a9a2dfa..d770a9bcc 100644
--- a/kit/Kit.cpp
+++ b/kit/Kit.cpp
@@ -1956,13 +1956,17 @@ bool globalPreinit(const std::string &loTemplate)
         LOG_FTL("No libreofficekit_hook_2 symbol in " << loadedLibrary << ": " << dlerror());
     }
 
-    LOG_TRC("lok_preinit(" << loTemplate << "/program\", \"file:///user\")");
+    LOG_TRC("Invoking lok_preinit(" << loTemplate << "/program\", \"file:///user\")");

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list