kit/ChildSession.cpp     |    9 +++++++++
 kit/Kit.cpp              |   10 ++++++++++
 net/Socket.hpp           |   41 ++++++++++++++++++++++++++++++++++++++---
 net/WebSocketHandler.hpp |   16 ++++++++++++++++
 4 files changed, 73 insertions(+), 3 deletions(-)

New commits:
commit 39a5f4ac30268ddbf012f7f4816edda3a8ddb6b4
Author:     Gabriel Masei <gabriel.ma...@1and1.ro>
AuthorDate: Fri Jul 10 15:22:35 2020 +0300
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Sun Jul 26 23:18:24 2020 +0200

    kit: disable parallel handling of messages while processing load and save
    
    The map._activate, among other actions, is sending indirectly some messages
    to the server like clientzoom and clientvisiblearea. If these messages are 
send
    before the document finishes processing the load message then there is
    a chance that a nodocloaded error will be thrown because there is a
    chance that the messages will be processed in parallel with load. This 
happens
    constantly for xlsx files. This is generated by the Unipoll mechanism which,
    in case of xlsx files, triggers a parallel processing.
    To avoid the above scenario a mechanism of disabling parallel processing of
    messages in kit was implemented and is used for load and save messages, for 
now.
    
    Change-Id: I4c83e72e600f92d0bb4f1f18cebe694e326256d0
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/98519
    Tested-by: Jenkins
    Tested-by: Michael Meeks <michael.me...@collabora.com>
    Reviewed-by: Michael Meeks <michael.me...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/99275
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Andras Timar <andras.ti...@collabora.com>

diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp
index b0aa69701..71440c290 100644
--- a/kit/ChildSession.cpp
+++ b/kit/ChildSession.cpp
@@ -212,6 +212,8 @@ bool ChildSession::_handleInput(const char *buffer, int 
length)
             return false;
         }
 
+        // Disable processing of other messages while loading document
+        InputProcessingManager processInput(getProtocol(), false);
         _isDocLoaded = loadDocument(buffer, length, tokens);
 
         LOG_TRC("isDocLoaded state after loadDocument: " << _isDocLoaded << 
'.');
@@ -379,6 +381,13 @@ bool ChildSession::_handleInput(const char *buffer, int 
length)
                 newTokens.push_back(firstLine.substr(4)); // Copy the 
remaining part.
                 return unoCommand(buffer, length, newTokens);
             }
+            else if (tokens[1].find(".uno:Save") != std::string::npos)
+            {
+                // Disable processing of other messages while saving document
+                InputProcessingManager processInput(getProtocol(), false);
+                return unoCommand(buffer, length, tokens);
+            }
+
             return unoCommand(buffer, length, tokens);
         }
         else if (tokens.equals(0, "selecttext"))
diff --git a/kit/Kit.cpp b/kit/Kit.cpp
index 3e4944740..4d20d27b4 100644
--- a/kit/Kit.cpp
+++ b/kit/Kit.cpp
@@ -2356,6 +2356,16 @@ protected:
         }
     }
 
+    virtual void enableProcessInput(bool enable = true) override
+    {
+        WebSocketHandler::enableProcessInput(enable);
+        // Wake up poll to process data from socket input buffer
+        if (enable)
+        {
+            _ksPoll.wakeup();
+        }
+    }
+
     void onDisconnect() override
     {
 #if !MOBILEAPP
diff --git a/net/Socket.hpp b/net/Socket.hpp
index 55cfe05bb..399d6b408 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -370,6 +370,10 @@ public:
     /// Will be called exactly once.
     virtual void onConnect(const std::shared_ptr<StreamSocket>& socket) = 0;
 
+    /// Enable/disable processing of incoming data at socket level.
+    virtual void enableProcessInput(bool /*enable*/){};
+    virtual bool processInputEnabled(){ return true; };
+
     /// Called after successful socket reads.
     virtual void handleIncomingMessage(SocketDisposition &disposition) = 0;
 
@@ -469,6 +473,32 @@ public:
     virtual void dumpState(std::ostream& os) = 0;
 };
 
+class InputProcessingManager
+{
+public:
+    InputProcessingManager(const std::shared_ptr<ProtocolHandlerInterface> 
&protocol, bool inputProcess)
+    : _protocol(protocol)
+    {
+        if (_protocol)
+        {
+            // Save previous state to be restored in destructor
+            _prevInputProcess = _protocol->processInputEnabled();
+            protocol->enableProcessInput(inputProcess);
+        }
+    }
+
+    ~InputProcessingManager()
+    {
+        // Restore previous state
+        if (_protocol)
+            _protocol->enableProcessInput(_prevInputProcess);
+    }
+
+private:
+    std::shared_ptr<ProtocolHandlerInterface> _protocol;
+    bool _prevInputProcess;
+};
+
 /// Handles non-blocking socket event polling.
 /// Only polls on N-Sockets and invokes callback and
 /// doesn't manage buffers or client data.
@@ -782,7 +812,8 @@ public:
         _sentHTTPContinue(false),
         _shutdownSignalled(false),
         _incomingFD(-1),
-        _readType(readType)
+        _readType(readType),
+        _inputProcessingEnabled(true)
     {
         LOG_DBG("StreamSocket ctor #" << fd);
 
@@ -1032,6 +1063,9 @@ public:
         return _incomingFD;
     }
 
+    bool processInputEnabled(){ return _inputProcessingEnabled; }
+    void enableProcessInput(bool enable = true){ _inputProcessingEnabled = 
enable; }
+
 protected:
 
     std::vector<std::pair<size_t, size_t>> findChunks(Poco::Net::HTTPRequest 
&request);
@@ -1046,7 +1080,7 @@ protected:
 
         _socketHandler->checkTimeout(now);
 
-        if (!events)
+        if (!events && _inBuffer.empty())
             return;
 
         // FIXME: need to close input, but not output (?)
@@ -1066,7 +1100,7 @@ protected:
 
         // If we have data, allow the app to consume.
         size_t oldSize = 0;
-        while (!_inBuffer.empty() && oldSize != _inBuffer.size())
+        while (!_inBuffer.empty() && oldSize != _inBuffer.size() && 
processInputEnabled())
         {
             oldSize = _inBuffer.size();
             _socketHandler->handleIncomingMessage(disposition);
@@ -1259,6 +1293,7 @@ protected:
     bool _shutdownSignalled;
     int _incomingFD;
     ReadType _readType;
+    std::atomic_bool _inputProcessingEnabled;
 };
 
 enum class WSOpCode : unsigned char {
diff --git a/net/WebSocketHandler.hpp b/net/WebSocketHandler.hpp
index 9c4ac5bb4..77ae3a264 100644
--- a/net/WebSocketHandler.hpp
+++ b/net/WebSocketHandler.hpp
@@ -815,6 +815,22 @@ protected:
         // but do reset the time to avoid pinging immediately after.
         _lastPingSentTime = std::chrono::steady_clock::now();
     }
+
+    virtual void enableProcessInput(bool enable = true) override
+    {
+        std::shared_ptr<StreamSocket> socket = _socket.lock();
+        if (socket)
+            socket->enableProcessInput(enable);
+    }
+
+    virtual bool processInputEnabled() override
+    {
+        std::shared_ptr<StreamSocket> socket = _socket.lock();
+        if (socket)
+            return socket->processInputEnabled();
+
+        return false;
+    }
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to