[Libreoffice-commits] online.git: wsd/LOOLWebSocket.hpp

Ashod Nakashian ashod.nakashian at collabora.co.uk
Mon Feb 13 06:54:01 UTC 2017


 wsd/LOOLWebSocket.hpp |   12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

New commits:
commit 9120fbabad552c22618509cfdc2cf73395e001b7
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date:   Sun Feb 12 23:47:43 2017 -0500

    wsd: use separate read/write locks in LOOLWebSocket
    
    When two sockets send data to each other in blocking
    mode, they can both wait until the other end-point's
    buffers are free enough to receive the data being
    sent. Since in LOOLWebSocket we lock both send and
    receive with the same lock, this prevents the
    reader thread from freeing the buffer while we try
    to send data. But since our peer is in the same
    dilemma, neither of us will make progress--deadlock.
    
    Since sockets are full-duplex, they are capable of
    handling two way communication concurrently. Poco
    seems to not share data between them either, so
    this seems safe.
    
    Change-Id: I1fd68cd4fb3b4250b93c8f94cd42e49ee78f6650
    Reviewed-on: https://gerrit.libreoffice.org/34194
    Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>

diff --git a/wsd/LOOLWebSocket.hpp b/wsd/LOOLWebSocket.hpp
index b1acd35..1408622 100644
--- a/wsd/LOOLWebSocket.hpp
+++ b/wsd/LOOLWebSocket.hpp
@@ -31,7 +31,8 @@
 class LOOLWebSocket : public Poco::Net::WebSocket
 {
 private:
-    std::mutex _mutex;
+    std::mutex _mutexRead;
+    std::mutex _mutexWrite;
 
 #if ENABLE_DEBUG
     static std::chrono::milliseconds getWebSocketDelay()
@@ -110,11 +111,12 @@ public:
         // Timeout is in microseconds. We don't need this, except to yield the cpu.
         static const Poco::Timespan waitTime(POLL_TIMEOUT_MS * 1000 / 10);
         static const Poco::Timespan waitZero(0);
-        std::unique_lock<std::mutex> lock(_mutex);
 
         while (poll(waitTime, Poco::Net::Socket::SELECT_READ))
         {
+            std::unique_lock<std::mutex> lockRead(_mutexRead);
             const int n = Poco::Net::WebSocket::receiveFrame(buffer, length, flags);
+            lockRead.unlock();
 
             if (n <= 0)
                 LOG_TRC("Got nothing (" << n << ")");
@@ -130,6 +132,7 @@ public:
             if ((flags & WebSocket::FRAME_OP_BITMASK) == WebSocket::FRAME_OP_PING)
             {
                 // Echo back the ping message.
+                std::unique_lock<std::mutex> lock(_mutexWrite);
                 if (Poco::Net::WebSocket::sendFrame(buffer, n, static_cast<int>(WebSocket::FRAME_FLAG_FIN) | WebSocket::FRAME_OP_PONG) != n)
                 {
                     LOG_WRN("Sending Pong failed.");
@@ -158,7 +161,7 @@ public:
         std::this_thread::sleep_for(getWebSocketDelay());
 #endif
         static const Poco::Timespan waitZero(0);
-        std::unique_lock<std::mutex> lock(_mutex);
+        std::unique_lock<std::mutex> lock(_mutexWrite);
 
         if (length >= LARGE_MESSAGE_SIZE)
         {
@@ -204,7 +207,8 @@ public:
     /// or, otherwise, close the socket without sending close frame, if it is.
     void shutdown(Poco::UInt16 statusCode, const std::string& statusMessage = "")
     {
-        std::unique_lock<std::mutex> lock(_mutex);
+        std::unique_lock<std::mutex> lockRead(_mutexRead);
+        std::unique_lock<std::mutex> lockWrite(_mutexWrite);
         try
         {
             // Calling shutdown, in case of error, would try to send a 'close' frame


More information about the Libreoffice-commits mailing list