wsd/LOOLWebSocket.hpp | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-)
New commits: commit f7bbd9072db7a71ff28ba178d5ca9eebe6cf4397 Author: Ashod Nakashian <ashod.nakash...@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 <ashnak...@gmail.com> Tested-by: Ashod Nakashian <ashnak...@gmail.com> Reviewed-on: https://gerrit.libreoffice.org/34213 Reviewed-by: Michael Meeks <michael.me...@collabora.com> Tested-by: Michael Meeks <michael.me...@collabora.com> diff --git a/wsd/LOOLWebSocket.hpp b/wsd/LOOLWebSocket.hpp index 86dc659..22e2891 100644 --- a/wsd/LOOLWebSocket.hpp +++ b/wsd/LOOLWebSocket.hpp @@ -31,10 +31,11 @@ class LOOLWebSocket : public Poco::Net::WebSocket { private: - std::mutex _mutex; + std::mutex _mutexRead; + std::mutex _mutexWrite; #if ENABLE_DEBUG - std::chrono::milliseconds getWebSocketDelay() + static std::chrono::milliseconds getWebSocketDelay() { unsigned long baseDelay = 0; unsigned long jitter = 0; @@ -108,7 +109,10 @@ public: 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 << ")"); @@ -119,11 +123,17 @@ public: } if ((flags & WebSocket::FRAME_OP_BITMASK) == WebSocket::FRAME_OP_PING) { - sendFrame(buffer, n, WebSocket::FRAME_FLAG_FIN | WebSocket::FRAME_OP_PONG); + // 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."); + return -1; + } } else if ((flags & WebSocket::FRAME_OP_BITMASK) == WebSocket::FRAME_OP_PONG) { - // In case we do send pongs in the future. + // In case we do send pings in the future. } else { @@ -131,6 +141,7 @@ public: } } + // Not ready for read. return -1; } @@ -141,13 +152,22 @@ public: // Delay sending the frame std::this_thread::sleep_for(getWebSocketDelay()); #endif - std::unique_lock<std::mutex> lock(_mutex); + std::unique_lock<std::mutex> lock(_mutexWrite); if (length >= LARGE_MESSAGE_SIZE) { const std::string nextmessage = "nextmessage: size=" + std::to_string(length); - Poco::Net::WebSocket::sendFrame(nextmessage.data(), nextmessage.size()); - LOG_TRC("Message is long, sent " + nextmessage); + const int size = nextmessage.size(); + + if (Poco::Net::WebSocket::sendFrame(nextmessage.data(), size) == size) + { + LOG_TRC("Sent long message preample: " + nextmessage); + } + else + { + LOG_WRN("Failed to send long message preample."); + return -1; + } } const int result = Poco::Net::WebSocket::sendFrame(buffer, length, flags); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits