[Libreoffice-commits] online.git: loolwsd/DocumentBroker.cpp loolwsd/test loolwsd/Unit.hpp
Ashod Nakashian
ashod.nakashian at collabora.co.uk
Sat May 21 03:43:33 UTC 2016
loolwsd/DocumentBroker.cpp | 6 ++++
loolwsd/Unit.hpp | 4 ++
loolwsd/test/UnitPrefork.cpp | 61 +++++++++++++++++++++++++------------------
3 files changed, 46 insertions(+), 25 deletions(-)
New commits:
commit 958f6ffcbdbeae39b78acfb7592096851388fb52
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date: Fri May 20 22:31:53 2016 -0400
loolwsd: fix UnitPrefork deadlock/corruption
Reading from the socket in the test is not
thread-safe, and was causing all sorts of
problems.
The new code adds a test API and reads the
incoming data through it and not directly
from the socket. In addition, the read is
synchronized.
Change-Id: Id13821a40a59e32fd8a14f733a47306aee42ada8
Reviewed-on: https://gerrit.libreoffice.org/25244
Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
Tested-by: Ashod Nakashian <ashnakash at gmail.com>
diff --git a/loolwsd/DocumentBroker.cpp b/loolwsd/DocumentBroker.cpp
index 3bb2bcc..de4d984 100644
--- a/loolwsd/DocumentBroker.cpp
+++ b/loolwsd/DocumentBroker.cpp
@@ -20,6 +20,7 @@
#include "LOOLProtocol.hpp"
#include "ClientSession.hpp"
#include "PrisonerSession.hpp"
+#include "Unit.hpp"
using namespace LOOLProtocol;
@@ -28,6 +29,11 @@ void ChildProcess::socketProcessor()
IoUtil::SocketProcessor(_ws,
[this](const std::vector<char>& payload)
{
+ if (UnitWSD::get().filterChildMessage(payload))
+ {
+ return true;
+ }
+
auto docBroker = this->_docBroker.lock();
if (docBroker)
{
diff --git a/loolwsd/Unit.hpp b/loolwsd/Unit.hpp
index dcdd36c..9cebfaa 100644
--- a/loolwsd/Unit.hpp
+++ b/loolwsd/Unit.hpp
@@ -134,6 +134,10 @@ public:
Poco::Net::HTTPServerResponse& /* response */)
{ return false; }
+ /// Child sent a message
+ virtual bool filterChildMessage(const std::vector<char>& /* payload */)
+ { return false; }
+
// ---------------- TileCache hooks ----------------
/// Called before the lookupTile call returns. Should always be called to fire events.
virtual void lookupTile(int part, int width, int height, int tilePosX, int tilePosY,
diff --git a/loolwsd/test/UnitPrefork.cpp b/loolwsd/test/UnitPrefork.cpp
index c265831..f9437bb 100644
--- a/loolwsd/test/UnitPrefork.cpp
+++ b/loolwsd/test/UnitPrefork.cpp
@@ -14,6 +14,9 @@
#include <sys/types.h>
#include <dirent.h>
+#include <mutex>
+#include <condition_variable>
+
#include "Common.hpp"
#include "IoUtil.hpp"
#include "LOOLProtocol.hpp"
@@ -32,11 +35,17 @@ class UnitPrefork : public UnitWSD
int _numStarted;
std::string _failure;
Poco::Timestamp _startTime;
+ size_t _totalPSS;
+ size_t _totalDirty;
+ std::mutex _mutex;
+ std::condition_variable _cv;
std::vector< std::shared_ptr<Poco::Net::WebSocket> > _childSockets;
public:
UnitPrefork()
- : _numStarted(0)
+ : _numStarted(0),
+ _totalPSS(0),
+ _totalDirty(0)
{
setHasKitHooks();
}
@@ -52,29 +61,9 @@ public:
numPrefork = NumToPrefork;
}
- void getMemory(const std::shared_ptr<Poco::Net::WebSocket> &socket,
- size_t &totalPSS, size_t &totalDirty)
+ virtual bool filterChildMessage(const std::vector<char>& payload)
{
- /// Fetch memory usage data from the last process ...
- socket->sendFrame("unit-memdump: \n", sizeof("unit-memdump: \n")-1);
-
- static const Poco::Timespan waitTime(COMMAND_TIMEOUT_MS * 1000);
- if (!socket->poll(waitTime, Poco::Net::Socket::SELECT_READ))
- {
- _failure = "Timed out waiting for child to respond to unit-memdump command.";
- return;
- }
-
- int flags;
- char buffer[4096];
- const int length = IoUtil::receiveFrame(*socket, buffer, sizeof (buffer), flags);
- if (length <= 0 || ((flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) == Poco::Net::WebSocket::FRAME_OP_CLOSE))
- {
- _failure = "Failed to read child response to unit-memdump command.";
- return;
- }
-
- const std::string memory = LOOLProtocol::getFirstLine(buffer, length);
+ const std::string memory = LOOLProtocol::getFirstLine(payload);
if (!memory.compare(0,6,"Error:"))
{
_failure = memory;
@@ -84,9 +73,31 @@ public:
Log::info("Got memory stats [" + memory + "].");
Poco::StringTokenizer tokens(memory, " ");
assert(tokens.count() == 2);
- totalPSS += atoi(tokens[0].c_str());
- totalDirty += atoi(tokens[1].c_str());
+ _totalPSS += atoi(tokens[0].c_str());
+ _totalDirty += atoi(tokens[1].c_str());
}
+
+ // Don't signal before wait.
+ std::unique_lock<std::mutex> lock(_mutex);
+ _cv.notify_one();
+ return true;
+ }
+
+ void getMemory(const std::shared_ptr<Poco::Net::WebSocket> &socket,
+ size_t &totalPSS, size_t &totalDirty)
+ {
+ std::unique_lock<std::mutex> lock(_mutex);
+
+ /// Fetch memory usage data from the last process ...
+ socket->sendFrame("unit-memdump: \n", sizeof("unit-memdump: \n"));
+
+ if (_cv.wait_for(lock, std::chrono::milliseconds(5 * 1000)) == std::cv_status::timeout)
+ {
+ _failure = "Timed out waiting for child to respond to unit-memdump.";
+ }
+
+ totalPSS = _totalPSS;
+ totalDirty = _totalDirty;
}
virtual void newChild(const std::shared_ptr<Poco::Net::WebSocket> &socket) override
More information about the Libreoffice-commits
mailing list