[Libreoffice-commits] online.git: Branch 'feature/lifecycle' - 35 commits - loleaflet/debug loleaflet/dist loleaflet/Makefile loleaflet/reference.html loleaflet/src loolwsd/ChildProcessSession.cpp loolwsd/ChildProcessSession.hpp loolwsd/configure.ac loolwsd/.gitignore loolwsd/LOKitHelper.hpp loolwsd/LOOLBroker.cpp loolwsd/LOOLKit.cpp loolwsd/LOOLSession.cpp loolwsd/LOOLSession.hpp loolwsd/LOOLWSD.cpp loolwsd/LOOLWSD.hpp loolwsd/loolwsd-systemplate-setup loolwsd/Makefile.am loolwsd/MasterProcessSession.cpp loolwsd/MasterProcessSession.hpp loolwsd/MessageQueue.cpp loolwsd/MessageQueue.hpp loolwsd/TileCache.cpp loolwsd/Util.cpp loolwsd/Util.hpp
Henry Castro
hcastro at collabora.com
Mon Dec 21 08:14:11 PST 2015
loleaflet/Makefile | 2
loleaflet/debug/document/document_simple_example.html | 13
loleaflet/dist/leaflet.css | 462 +-----
loleaflet/dist/loleaflet.css | 18
loleaflet/dist/partsPreviewControl.css | 37
loleaflet/dist/scrollBar.css | 13
loleaflet/dist/searchControl.css | 8
loleaflet/dist/selectionMarkers.css | 13
loleaflet/dist/tabsControl.css | 29
loleaflet/dist/toolbar.css | 64
loleaflet/reference.html | 150 +
loleaflet/src/control/Control.ColumnHeader.js | 24
loleaflet/src/control/Control.Dialog.js | 1
loleaflet/src/control/Control.PartsPreview.js | 63
loleaflet/src/control/Control.RowHeader.js | 27
loleaflet/src/control/Control.Scroll.js | 1
loleaflet/src/control/Control.Tabs.js | 4
loleaflet/src/control/Control.js | 9
loleaflet/src/control/Scroll.js | 6
loleaflet/src/core/Socket.js | 43
loleaflet/src/layer/tile/CalcTileLayer.js | 7
loleaflet/src/layer/tile/GridLayer.js | 6
loleaflet/src/layer/tile/TileLayer.js | 40
loleaflet/src/map/Map.js | 5
loolwsd/.gitignore | 8
loolwsd/ChildProcessSession.cpp | 735 +++++++++
loolwsd/ChildProcessSession.hpp | 98 +
loolwsd/LOKitHelper.hpp | 2
loolwsd/LOOLBroker.cpp | 874 +++++++++++
loolwsd/LOOLKit.cpp | 665 ++++++++
loolwsd/LOOLSession.cpp | 1376 ------------------
loolwsd/LOOLSession.hpp | 117 -
loolwsd/LOOLWSD.cpp | 605 +------
loolwsd/LOOLWSD.hpp | 10
loolwsd/Makefile.am | 19
loolwsd/MasterProcessSession.cpp | 664 ++++++++
loolwsd/MasterProcessSession.hpp | 86 +
loolwsd/MessageQueue.cpp | 8
loolwsd/MessageQueue.hpp | 3
loolwsd/TileCache.cpp | 8
loolwsd/Util.cpp | 128 +
loolwsd/Util.hpp | 23
loolwsd/configure.ac | 2
loolwsd/loolwsd-systemplate-setup | 76
44 files changed, 4135 insertions(+), 2417 deletions(-)
New commits:
commit 9ffa4ec6fc806f6565f4225ac602130b782fd414
Author: Henry Castro <hcastro at collabora.com>
Date: Mon Dec 21 09:54:52 2015 -0500
loolwsd: Merged collaborative prototype
Enabled the broker and kit processes.
Change-Id: I9afedbccac35732ffe846494cae8135d306e6311
diff --git a/loolwsd/ChildProcessSession.cpp b/loolwsd/ChildProcessSession.cpp
index dd56da0..cf75086 100644
--- a/loolwsd/ChildProcessSession.cpp
+++ b/loolwsd/ChildProcessSession.cpp
@@ -211,114 +211,15 @@ extern "C"
{
static void myCallback(int nType, const char* pPayload, void* pData)
{
- ChildProcessSession *srv = reinterpret_cast<ChildProcessSession *>(pData);
+ /*pid_t tid = syscall(SYS_gettid);
+ std::cout << tid << " callbackWorker : " << priv->m_nViewId << " " << std::string(callbackTypeToString(nType)) << " " << std::string(pPayload ? pPayload : "(nil)") << std::endl;*/
- switch ((LibreOfficeKitCallbackType) nType)
- {
- case LOK_CALLBACK_INVALIDATE_TILES:
- {
- int curPart = srv->_loKitDocument->pClass->getPart(srv->_loKitDocument);
- srv->sendTextFrame("curpart: part=" + std::to_string(curPart));
- if (srv->_docType == "text")
- {
- curPart = 0;
- }
- StringTokenizer tokens(std::string(pPayload), " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
- if (tokens.count() == 4)
- {
- int x, y, width, height;
-
- try {
- x = std::stoi(tokens[0]);
- y = std::stoi(tokens[1]);
- width = std::stoi(tokens[2]);
- height = std::stoi(tokens[3]);
- }
- catch (std::out_of_range&)
- {
- // something went wrong, invalidate everything
- Application::instance().logger().information(Util::logPrefix() + "Ignoring integer values out of range: " + pPayload);
- x = 0;
- y = 0;
- width = INT_MAX;
- height = INT_MAX;
- }
-
- srv->sendTextFrame("invalidatetiles:"
- " part=" + std::to_string(curPart) +
- " x=" + std::to_string(x) +
- " y=" + std::to_string(y) +
- " width=" + std::to_string(width) +
- " height=" + std::to_string(height));
- }
- else
- {
- srv->sendTextFrame("invalidatetiles: " + std::string(pPayload));
- }
- }
- break;
- case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR:
- srv->sendTextFrame("invalidatecursor: " + std::string(pPayload));
- break;
- case LOK_CALLBACK_TEXT_SELECTION:
- srv->sendTextFrame("textselection: " + std::string(pPayload));
- break;
- case LOK_CALLBACK_TEXT_SELECTION_START:
- srv->sendTextFrame("textselectionstart: " + std::string(pPayload));
- break;
- case LOK_CALLBACK_TEXT_SELECTION_END:
- srv->sendTextFrame("textselectionend: " + std::string(pPayload));
- break;
- case LOK_CALLBACK_CURSOR_VISIBLE:
- srv->sendTextFrame("cursorvisible: " + std::string(pPayload));
- break;
- case LOK_CALLBACK_GRAPHIC_SELECTION:
- srv->sendTextFrame("graphicselection: " + std::string(pPayload));
- break;
- case LOK_CALLBACK_CELL_CURSOR:
- srv->sendTextFrame("cellcursor: " + std::string(pPayload));
- break;
- case LOK_CALLBACK_CELL_FORMULA:
- srv->sendTextFrame("cellformula: " + std::string(pPayload));
- break;
- case LOK_CALLBACK_MOUSE_POINTER:
- srv->sendTextFrame("mousepointer: " + std::string(pPayload));
- break;
- case LOK_CALLBACK_HYPERLINK_CLICKED:
- srv->sendTextFrame("hyperlinkclicked: " + std::string(pPayload));
- break;
- case LOK_CALLBACK_STATE_CHANGED:
- srv->sendTextFrame("statechanged: " + std::string(pPayload));
- break;
- case LOK_CALLBACK_STATUS_INDICATOR_START:
- srv->sendTextFrame("statusindicatorstart:");
- break;
- case LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE:
- srv->sendTextFrame("statusindicatorsetvalue: " + std::string(pPayload));
- break;
- case LOK_CALLBACK_STATUS_INDICATOR_FINISH:
- srv->sendTextFrame("statusindicatorfinish:");
- break;
- case LOK_CALLBACK_SEARCH_NOT_FOUND:
- srv->sendTextFrame("searchnotfound: " + std::string(pPayload));
- break;
- case LOK_CALLBACK_SEARCH_RESULT_SELECTION:
- srv->sendTextFrame("searchresultselection: " + std::string(pPayload));
- break;
- case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED:
- srv->getStatus("", 0);
- srv->getPartPageRectangles("", 0);
- break;
- case LOK_CALLBACK_SET_PART:
- srv->sendTextFrame("setpart: " + std::string(pPayload));
- break;
- case LOK_CALLBACK_UNO_COMMAND_RESULT:
- srv->sendTextFrame("unocommandresult: " + std::string(pPayload));
- break;
- }
+ ChildProcessSession::_callbackQueue.enqueueNotification(new CallBackNotification(nType, pPayload ? pPayload : "(nil)", pData));
+ //std::string aPayLoad(pPayload ? pPayload : "(nil)");
}
}
+
bool ChildProcessSession::loadDocument(const char *buffer, int length, StringTokenizer& tokens)
{
int part = -1;
diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp
index f20a8dd..3c6917a 100644
--- a/loolwsd/LOOLKit.cpp
+++ b/loolwsd/LOOLKit.cpp
@@ -109,25 +109,38 @@ public:
void callback(int nType, std::string& rPayload, void* pData)
{
ChildProcessSession *srv = reinterpret_cast<ChildProcessSession *>(pData);
- pid_t tid = syscall(SYS_gettid);
- //if ( nType == LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR )
- std::cout << tid << " callback : " << srv->_viewId << " " << callbackTypeToString(nType) << " " << rPayload << std::endl;
-
- switch ( nType )
+ switch ((LibreOfficeKitCallbackType) nType)
{
case LOK_CALLBACK_INVALIDATE_TILES:
{
- //int curPart = srv->_loKitDocument->pClass->getPart(srv->_loKitDocument);
- int curPart = 0;
+ int curPart = srv->_loKitDocument->pClass->getPart(srv->_loKitDocument);
srv->sendTextFrame("curpart: part=" + std::to_string(curPart));
+ if (srv->_docType == "text")
+ {
+ curPart = 0;
+ }
StringTokenizer tokens(rPayload, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
if (tokens.count() == 4)
{
- int x(std::stoi(tokens[0]));
- int y(std::stoi(tokens[1]));
- int width(std::stoi(tokens[2]));
- int height(std::stoi(tokens[3]));
+ int x, y, width, height;
+
+ try {
+ x = std::stoi(tokens[0]);
+ y = std::stoi(tokens[1]);
+ width = std::stoi(tokens[2]);
+ height = std::stoi(tokens[3]);
+ }
+ catch (std::out_of_range&)
+ {
+ // something went wrong, invalidate everything
+ std::cout << Util::logPrefix() << "Ignoring integer values out of range: " << rPayload << std::endl;
+ x = 0;
+ y = 0;
+ width = INT_MAX;
+ height = INT_MAX;
+ }
+
srv->sendTextFrame("invalidatetiles:"
" part=" + std::to_string(curPart) +
" x=" + std::to_string(x) +
@@ -135,22 +148,12 @@ public:
" width=" + std::to_string(width) +
" height=" + std::to_string(height));
}
- else {
+ else
+ {
srv->sendTextFrame("invalidatetiles: " + rPayload);
}
}
break;
- case LOK_CALLBACK_STATUS_INDICATOR_START:
- srv->sendTextFrame("statusindicatorstart:");
- break;
-
- case LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE:
- srv->sendTextFrame("statusindicatorsetvalue: " + rPayload);
- break;
-
- case LOK_CALLBACK_STATUS_INDICATOR_FINISH:
- srv->sendTextFrame("statusindicatorfinish:");
- break;
case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR:
srv->sendTextFrame("invalidatecursor: " + rPayload);
break;
@@ -169,25 +172,49 @@ public:
case LOK_CALLBACK_GRAPHIC_SELECTION:
srv->sendTextFrame("graphicselection: " + rPayload);
break;
+ case LOK_CALLBACK_CELL_CURSOR:
+ srv->sendTextFrame("cellcursor: " + rPayload);
+ break;
+ case LOK_CALLBACK_CELL_FORMULA:
+ srv->sendTextFrame("cellformula: " + rPayload);
+ break;
+ case LOK_CALLBACK_MOUSE_POINTER:
+ srv->sendTextFrame("mousepointer: " + rPayload);
+ break;
case LOK_CALLBACK_HYPERLINK_CLICKED:
srv->sendTextFrame("hyperlinkclicked: " + rPayload);
break;
case LOK_CALLBACK_STATE_CHANGED:
srv->sendTextFrame("statechanged: " + rPayload);
break;
+ case LOK_CALLBACK_STATUS_INDICATOR_START:
+ srv->sendTextFrame("statusindicatorstart:");
+ break;
+ case LOK_CALLBACK_STATUS_INDICATOR_SET_VALUE:
+ srv->sendTextFrame("statusindicatorsetvalue: " + rPayload);
+ break;
+ case LOK_CALLBACK_STATUS_INDICATOR_FINISH:
+ srv->sendTextFrame("statusindicatorfinish:");
+ break;
case LOK_CALLBACK_SEARCH_NOT_FOUND:
srv->sendTextFrame("searchnotfound: " + rPayload);
break;
+ case LOK_CALLBACK_SEARCH_RESULT_SELECTION:
+ srv->sendTextFrame("searchresultselection: " + rPayload);
+ break;
case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED:
srv->getStatus("", 0);
+ srv->getPartPageRectangles("", 0);
break;
case LOK_CALLBACK_SET_PART:
srv->sendTextFrame("setpart: " + rPayload);
break;
+ case LOK_CALLBACK_UNO_COMMAND_RESULT:
+ srv->sendTextFrame("unocommandresult: " + rPayload);
+ break;
}
}
-
void run()
{
while ( true )
@@ -390,6 +417,13 @@ void run_lok_main(const std::string &loSubPath, Poco::UInt64 _childId, const std
std::cout << Util::logPrefix() << "Cannot set thread name :" << strerror(errno) << std::endl;
#endif
+ if (std::getenv("SLEEPFORDEBUGGER"))
+ {
+ std::cout << "Sleeping " << std::getenv("SLEEPFORDEBUGGER") << " seconds, attach process "
+ << Process::id() << " in debugger now." << std::endl;
+ Thread::sleep(std::stoul(std::getenv("SLEEPFORDEBUGGER")) * 1000);
+ }
+
try
{
#ifdef __APPLE__
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index 2bb61a1..d543c32 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -153,91 +153,6 @@ using Poco::URI;
namespace
{
- ThreadLocal<std::string> sourceForLinkOrCopy;
- ThreadLocal<Path> destinationForLinkOrCopy;
-
- int linkOrCopyFunction(const char *fpath,
- const struct stat* /*sb*/,
- int typeflag,
- struct FTW* /*ftwbuf*/)
- {
- if (strcmp(fpath, sourceForLinkOrCopy->c_str()) == 0)
- return 0;
-
- assert(fpath[strlen(sourceForLinkOrCopy->c_str())] == '/');
- const char *relativeOldPath = fpath + strlen(sourceForLinkOrCopy->c_str()) + 1;
-
-#ifdef __APPLE__
- if (strcmp(relativeOldPath, "PkgInfo") == 0)
- return 0;
-#endif
-
- Path newPath(*destinationForLinkOrCopy, Path(relativeOldPath));
-
- switch (typeflag)
- {
- case FTW_F:
- File(newPath.parent()).createDirectories();
- if (link(fpath, newPath.toString().c_str()) == -1)
- {
- Application::instance().logger().error(Util::logPrefix() +
- "link(\"" + fpath + "\",\"" + newPath.toString() + "\") failed: " +
- strerror(errno));
- exit(1);
- }
- break;
- case FTW_DP:
- {
- struct stat st;
- if (stat(fpath, &st) == -1)
- {
- Application::instance().logger().error(Util::logPrefix() +
- "stat(\"" + fpath + "\") failed: " +
- strerror(errno));
- return 1;
- }
- File(newPath).createDirectories();
- struct utimbuf ut;
- ut.actime = st.st_atime;
- ut.modtime = st.st_mtime;
- if (utime(newPath.toString().c_str(), &ut) == -1)
- {
- Application::instance().logger().error(Util::logPrefix() +
- "utime(\"" + newPath.toString() + "\", &ut) failed: " +
- strerror(errno));
- return 1;
- }
- }
- break;
- case FTW_DNR:
- Application::instance().logger().error(Util::logPrefix() +
- "Cannot read directory '" + fpath + "'");
- return 1;
- case FTW_NS:
- Application::instance().logger().error(Util::logPrefix() +
- "nftw: stat failed for '" + fpath + "'");
- return 1;
- case FTW_SLN:
- Application::instance().logger().information(Util::logPrefix() +
- "nftw: symlink to nonexistent file: '" + fpath + "', ignored");
- break;
- default:
- assert(false);
- }
- return 0;
- }
-
- void linkOrCopy(const std::string& source, const Path& destination)
- {
- *sourceForLinkOrCopy = source;
- if (sourceForLinkOrCopy->back() == '/')
- sourceForLinkOrCopy->pop_back();
- *destinationForLinkOrCopy = destination;
- if (nftw(source.c_str(), linkOrCopyFunction, 10, FTW_DEPTH) == -1)
- Application::instance().logger().error(Util::logPrefix() +
- "linkOrCopy: nftw() failed for '" + source + "'");
- }
-
void dropCapability(
#ifdef __linux
cap_value_t capability
@@ -752,7 +667,6 @@ std::string LOOLWSD::childRoot;
std::string LOOLWSD::loSubPath = "lo";
std::string LOOLWSD::jail;
Poco::NamedMutex LOOLWSD::_namedMutexLOOL("loolwsd");
-Poco::SharedMemory LOOLWSD::_sharedForkChild("loolwsd", sizeof(bool), Poco::SharedMemory::AM_WRITE);
int LOOLWSD::_numPreSpawnedChildren = 10;
bool LOOLWSD::doTest = false;
@@ -916,299 +830,6 @@ void LOOLWSD::displayHelp()
helpFormatter.format(std::cout);
}
-// Writer, Impress or Calc
-void LOOLWSD::componentMain()
-{
-#ifdef __linux
- if (prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("libreofficekit"), 0, 0, 0) != 0)
- std::cout << Util::logPrefix() << "Cannot set thread name :" << strerror(errno) << std::endl;
-
- setSignals(false);
-#endif
-
- try
- {
- _namedMutexLOOL.lock();
-
- Path jailPath = Path::forDirectory(LOOLWSD::childRoot + Path::separator() + std::to_string(_childId));
- File(jailPath).createDirectory();
-
- Path jailLOInstallation(jailPath, LOOLWSD::loSubPath);
- jailLOInstallation.makeDirectory();
- File(jailLOInstallation).createDirectory();
-
- // Copy (link) LO installation and other necessary files into it from the template
-
- linkOrCopy(LOOLWSD::sysTemplate, jailPath);
- linkOrCopy(LOOLWSD::loTemplate, jailLOInstallation);
-
- // We need this because sometimes the hostname is not resolved
- std::vector<std::string> networkFiles = {"/etc/host.conf", "/etc/hosts", "/etc/nsswitch.conf", "/etc/resolv.conf"};
- for (std::vector<std::string>::iterator it = networkFiles.begin(); it != networkFiles.end(); ++it)
- {
- File networkFile(*it);
- if (networkFile.exists())
- {
- networkFile.copyTo(Path(jailPath, "/etc").toString());
- }
- }
-#ifdef __linux
- // Create the urandom and random devices
- File(Path(jailPath, "/dev")).createDirectory();
- if (mknod((jailPath.toString() + "/dev/random").c_str(),
- S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
- makedev(1, 8)) != 0)
- {
- Application::instance().logger().error(Util::logPrefix() +
- "mknod(" + jailPath.toString() + "/dev/random) failed: " +
- strerror(errno));
-
- }
- if (mknod((jailPath.toString() + "/dev/urandom").c_str(),
- S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
- makedev(1, 9)) != 0)
- {
- Application::instance().logger().error(Util::logPrefix() +
- "mknod(" + jailPath.toString() + "/dev/urandom) failed: " +
- strerror(errno));
- }
-#endif
-
- Application::instance().logger().information("componentMain -> chroot(\"" + jailPath.toString() + "\")");
- if (chroot(jailPath.toString().c_str()) == -1)
- {
- logger().error("chroot(\"" + jailPath.toString() + "\") failed: " + strerror(errno));
- exit(Application::EXIT_UNAVAILABLE);
- }
-
- if (chdir("/") == -1)
- {
- logger().error(std::string("chdir(\"/\") in jail failed: ") + strerror(errno));
- exit(Application::EXIT_UNAVAILABLE);
- }
-
-#ifdef __linux
- dropCapability(CAP_SYS_CHROOT);
- dropCapability(CAP_MKNOD);
- dropCapability(CAP_FOWNER);
-#else
- dropCapability();
-#endif
-
- if (std::getenv("SLEEPFORDEBUGGER"))
- {
- std::cout << "Sleeping " << std::getenv("SLEEPFORDEBUGGER") << " seconds, " <<
- "attach process " << Process::id() << " in debugger now." << std::endl;
- Thread::sleep(std::stoul(std::getenv("SLEEPFORDEBUGGER")) * 1000);
- }
-
-#ifdef __APPLE__
- LibreOfficeKit *loKit(lok_init_2(("/" + loSubPath + "/Frameworks").c_str(), "file:///user"));
-#else
- LibreOfficeKit *loKit(lok_init_2(("/" + loSubPath + "/program").c_str(), "file:///user"));
-#endif
-
- if (!loKit)
- {
- logger().fatal(Util::logPrefix() + "LibreOfficeKit initialisation failed");
- exit(Application::EXIT_UNAVAILABLE);
- }
-
- _namedMutexLOOL.unlock();
-
- // Open websocket connection between the child process and the
- // parent. The parent forwards us requests that it can't handle.
-
- HTTPClientSession cs("127.0.0.1", MASTER_PORT_NUMBER);
- cs.setTimeout(0);
- HTTPRequest request(HTTPRequest::HTTP_GET, LOOLWSD::CHILD_URI);
- HTTPResponse response;
- std::shared_ptr<WebSocket> ws(new WebSocket(cs, request, response));
-
- std::shared_ptr<ChildProcessSession> session(new ChildProcessSession(ws, loKit, nullptr, std::to_string(_childId)));
-
- ws->setReceiveTimeout(0);
-
- std::string hello("child " + std::to_string(_childId) + " " + std::to_string(Process::id()));
- session->sendTextFrame(hello);
-
- TileQueue queue;
- Thread queueHandlerThread;
- QueueHandler handler(queue);
-
- handler.setSession(session);
- queueHandlerThread.start(handler);
-
- int flags;
- int n;
- do
- {
- char buffer[1024];
- n = ws->receiveFrame(buffer, sizeof(buffer), flags);
-
- if (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE)
- {
- std::string firstLine = getFirstLine(buffer, n);
- StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
-
- // The only kind of messages a child process receives are the single-line ones (?)
- assert(firstLine.size() == static_cast<std::string::size_type>(n));
-
- queue.put(firstLine);
- }
- }
- while (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE);
-
- queue.clear();
- queue.put("eof");
- queueHandlerThread.join();
-
- // Destroy lokit document
- if (session->_loKitDocument)
- session->_loKitDocument->pClass->destroy(session->_loKitDocument);
-
- // Destroy LibreOfficeKit
- loKit->pClass->destroy(loKit);
-
- // wait to finish lo_startmain thread
- pthread_exit(0);
- }
- catch (Exception& exc)
- {
- logger().log(Util::logPrefix() + "Exception: " + exc.what());
- }
- catch (std::exception& exc)
- {
- logger().error(Util::logPrefix() + "Exception: " + exc.what());
- }
-
- exit(Application::EXIT_OK);
-}
-
-int LOOLWSD::createComponent()
-{
- int pid;
-
- _childId = Util::rng::getNext();
-
- if ((pid = fork()) == -1)
- {
- std::cout << "Fork failed." << std::endl;
- return Application::EXIT_UNAVAILABLE;
- }
-
- if (!pid)
- {
- componentMain();
- }
-
- MasterProcessSession::_childProcesses[pid] = _childId;
-
- return Application::EXIT_OK;
-}
-
-void LOOLWSD::startupComponent(int nComponents)
-{
- for (int nCntr = nComponents; nCntr; nCntr--)
- {
- if (createComponent() < 0)
- break;
- }
-}
-
-void LOOLWSD::desktopMain()
-{
-#ifdef __linux
- if (prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("loolbroker"), 0, 0, 0) != 0)
- std::cout << Util::logPrefix() << "Cannot set thread name :" << strerror(errno) << std::endl;
-
- setSignals(false);
-#endif
-
- startupComponent(_numPreSpawnedChildren);
-
- while (MasterProcessSession::_childProcesses.size() > 0)
- {
- int status;
- pid_t pid = waitpid(-1, &status, WUNTRACED | WNOHANG);
- if (pid > 0)
- {
- if ( MasterProcessSession::_childProcesses.find(pid) != MasterProcessSession::_childProcesses.end() )
- {
- if ((WIFEXITED(status) || WIFSIGNALED(status) || WTERMSIG(status) ) )
- {
- std::cout << Util::logPrefix() << "One of our known child processes died :" << std::to_string(pid) << std::endl;
- // remove chroot child
- File aWorkSpace(LOOLWSD::childRoot + Path::separator() +
- std::to_string(MasterProcessSession::_childProcesses[pid]));
- if (aWorkSpace.exists())
- aWorkSpace.remove(true);
-
- MasterProcessSession::_childProcesses.erase(pid);
- }
-
- if ( WCOREDUMP(status) )
- std::cout << Util::logPrefix() << "The child process [" << pid << "] produced a core dump." << std::endl;
-
- if ( WIFSTOPPED(status) )
- std::cout << Util::logPrefix() << "The child process was stopped by delivery of a signal." << std::endl;
-
- if ( WSTOPSIG(status) )
- std::cout << Util::logPrefix() << "The child process was stopped." << std::endl;
-
- if ( WIFCONTINUED(status) )
- std::cout << Util::logPrefix() << "The child process was resumed." << std::endl;
- }
- else
- {
- std::cout << Util::logPrefix() << "None of our known child processes died :" << std::to_string(pid) << std::endl;
- }
- }
- else if (pid < 0)
- std::cout << Util::logPrefix() << "Child error: " << strerror(errno);
-
- if (!LOOLWSD::isShutDown && _sharedForkChild.begin()[0] > 0 )
- {
- _namedMutexLOOL.lock();
- _sharedForkChild.begin()[0] = _sharedForkChild.begin()[0] - 1;
- std::cout << Util::logPrefix() << "Create child session, fork new one" << std::endl;
- _namedMutexLOOL.unlock();
- if (createComponent() < 0 )
- break;
- }
-
- ++timeoutCounter;
- if (timeoutCounter == INTERVAL_PROBES)
- {
- timeoutCounter = 0;
- sleep(MAINTENANCE_INTERVAL);
- }
- }
-
- exit(Application::EXIT_OK);
-}
-
-
-int LOOLWSD::createDesktop()
-{
- int pid;
-
- if ((pid = fork()) == -1)
- {
- std::cout << "createDesktop fork failed." << std::endl;
- return Application::EXIT_UNAVAILABLE;
- }
-
- if (!pid)
- {
- desktopMain();
- }
-
- MasterProcessSession::_childProcesses[pid] = pid;
-
- return Application::EXIT_OK;
-}
-
int LOOLWSD::createBroker()
{
Process::Args args;
diff --git a/loolwsd/LOOLWSD.hpp b/loolwsd/LOOLWSD.hpp
index 3f7cfee..e14b0e4 100644
--- a/loolwsd/LOOLWSD.hpp
+++ b/loolwsd/LOOLWSD.hpp
@@ -42,7 +42,6 @@ public:
static std::string childRoot;
static std::string loSubPath;
static std::string jail;
- static Poco::SharedMemory _sharedForkChild;
static Poco::NamedMutex _namedMutexLOOL;
static Poco::UInt64 _childId;
commit 7c224aced869222466339fe859d98ca8d03c6786
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date: Sun Dec 20 12:59:26 2015 -0500
loolwsd: Nominal logger and fixes
Nominal logging interface and a fix to using Poco
Application from LOOLKit, which is not a Poco App,
which caused core dump.
Logs now include process name.
Added logs to strategic places and some cleanups.
Change-Id: Ib7dcc4f1033dddf7c87cd2e786a91f5b482fb312
diff --git a/loolwsd/ChildProcessSession.cpp b/loolwsd/ChildProcessSession.cpp
index b74138b..dd56da0 100644
--- a/loolwsd/ChildProcessSession.cpp
+++ b/loolwsd/ChildProcessSession.cpp
@@ -18,7 +18,6 @@
#include <Poco/String.h>
#include <Poco/StringTokenizer.h>
#include <Poco/URI.h>
-#include <Poco/Util/Application.h>
#include "ChildProcessSession.hpp"
#include "LOKitHelper.hpp"
@@ -38,7 +37,6 @@ using Poco::Process;
using Poco::ProcessHandle;
using Poco::StringTokenizer;
using Poco::URI;
-using Poco::Util::Application;
Poco::NotificationQueue ChildProcessSession::_callbackQueue;
Poco::Mutex ChildProcessSession::_mutex;
@@ -67,11 +65,11 @@ ChildProcessSession::~ChildProcessSession()
bool ChildProcessSession::handleInput(const char *buffer, int length)
{
+ Log::info(_kindString + ",Input," + getAbbreviatedMessage(buffer, length));
+
std::string firstLine = getFirstLine(buffer, length);
StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
- Application::instance().logger().information(Util::logPrefix() + _kindString + ",Input," + getAbbreviatedMessage(buffer, length));
-
if (tokens[0] == "canceltiles")
{
// this command makes sense only on the command queue level, nothing
@@ -363,7 +361,7 @@ bool ChildProcessSession::loadDocument(const char *buffer, int length, StringTok
if ((_loKitDocument = _loKit->pClass->documentLoad(_loKit, aUri.toString().c_str())) == NULL)
{
sendTextFrame("error: cmd=load kind=failed");
- Application::instance().logger().information(Util::logPrefix() + "Failed to load: " + aUri.toString() + ", error is: " + _loKit->pClass->getError(_loKit));
+ Log::error("Failed to load: " + aUri.toString() + ", error is: " + _loKit->pClass->getError(_loKit));
return false;
}
@@ -435,7 +433,7 @@ bool ChildProcessSession::getStatus(const char* /*buffer*/, int /*length*/)
StringTokenizer tokens(status, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
if (!getTokenString(tokens[1], "type", _docType))
{
- Application::instance().logger().information(Util::logPrefix() + "failed to get document type from" + status);
+ Log::error("failed to get document type from" + status);
}
sendTextFrame(status);
diff --git a/loolwsd/LOOLBroker.cpp b/loolwsd/LOOLBroker.cpp
index 5a64598..cca628e 100644
--- a/loolwsd/LOOLBroker.cpp
+++ b/loolwsd/LOOLBroker.cpp
@@ -233,7 +233,7 @@ namespace
}
if (setuid(LOOLWSD::uid) != 0)
{
- Application::instance().logger().error(std::string("setuid() failed: ") + strerror(errno));
+ Log::error(std::string("setuid() failed: ") + strerror(errno));
}
}
#endif
@@ -368,7 +368,6 @@ public:
{
Process::PID nPID;
- //std::cout << Util::logPrefix() << "Broker,Input," << aMessage << std::endl;
StringTokenizer tokens(aMessage, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
if (tokens[0] == "request" && tokens.count() == 3)
{
@@ -469,6 +468,7 @@ public:
}
pStart = aBuffer;
pEnd = aBuffer + nBytes;
+ std::cout << Util::logPrefix() << "Broker readFIFO [" << std::string(pStart, nBytes) << "]" << std::endl;
}
}
@@ -565,6 +565,7 @@ static int createLibreOfficeKit(bool sharePages, std::string loSubPath, Poco::UI
ProcessHandle procChild = Process::launch(executable, args);
child = procChild.id();
+ std::cout << Util::logPrefix() << "Launched kit process: " << child << std::endl;
if ( ( nFIFOWriter = open(pipe.c_str(), O_WRONLY) ) < 0 )
{
@@ -582,7 +583,9 @@ static int startupLibreOfficeKit(bool sharePages, int nLOKits,
{
Process::PID pId = -1;
- std::cout << Util::logPrefix() << "starting " << nLOKits << " LoKit instaces." << std::endl;
+ std::cout << Util::logPrefix() << "starting " << nLOKits << " LoKit instaces."
+ << " Shared: " << sharePages << ", loSubPath: " << loSubPath
+ << ", child: " << child << std::endl;
for (int nCntr = nLOKits; nCntr; nCntr--)
{
if ( (pId = createLibreOfficeKit(sharePages, loSubPath, child)) < 0)
@@ -592,7 +595,7 @@ static int startupLibreOfficeKit(bool sharePages, int nLOKits,
}
}
- return pId;
+ return pId;
}
// Broker process
@@ -605,6 +608,8 @@ int main(int argc, char** argv)
std::string loTemplate;
int _numPreSpawnedChildren = 0;
+ Log::initialize("brk");
+
for (int i = 0; i < argc; ++i)
{
char *cmd = argv[i];
@@ -635,9 +640,7 @@ int main(int argc, char** argv)
}
else if (strstr(cmd, "--numprespawns=") == cmd)
{
- std::cout << "CMD: " << cmd << std::endl;
eq = strchrnul(cmd, '=');
- std::cout << "EQ: " << std::string(eq + 1) << std::endl;
if (*eq)
_numPreSpawnedChildren = std::stoi(std::string(++eq));
}
@@ -697,8 +700,6 @@ int main(int argc, char** argv)
std::cout << Util::logPrefix() << aError.what() << std::endl;
}
- std::cout << "In Broker!" << std::endl;
-
const Poco::UInt64 _childId = Util::rng::getNext();
Path jailPath = Path::forDirectory(childRoot + Path::separator() + std::to_string(_childId));
diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp
index af0b5f6..f20a8dd 100644
--- a/loolwsd/LOOLKit.cpp
+++ b/loolwsd/LOOLKit.cpp
@@ -14,11 +14,11 @@
#include <sys/prctl.h>
#include <sys/poll.h>
#include <sys/syscall.h>
+#include <signal.h>
#include <memory>
#include <iostream>
-#include <Poco/Util/Application.h>
#include <Poco/Net/WebSocket.h>
#include <Poco/Net/HTTPClientSession.h>
#include <Poco/Net/HTTPRequest.h>
@@ -232,15 +232,28 @@ public:
{
#ifdef __linux
if (prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("queue_handler"), 0, 0, 0) != 0)
- std::cout << Util::logPrefix() << "Cannot set thread name :" << strerror(errno) << std::endl;
+ Log::error(std::string("Cannot set thread name :") + strerror(errno));
#endif
- while (true)
+ try
{
- std::string input = _queue.get();
- if (input == "eof")
- break;
- if (!_session->handleInput(input.c_str(), input.size()))
- break;
+ while (true)
+ {
+ std::string input = _queue.get();
+ if (input == "eof")
+ break;
+ if (!_session->handleInput(input.c_str(), input.size()))
+ break;
+ }
+ }
+ catch(std::exception& ex)
+ {
+ Log::error(std::string("Exception: ") + ex.what());
+ raise(SIGABRT);
+ }
+ catch(...)
+ {
+ Log::error("Unknown Exception.");
+ raise(SIGABRT);
}
}
@@ -258,6 +271,7 @@ public:
_childId(childId),
_threadId(threadId)
{
+ std::cout << Util::logPrefix() << "New connection in child: " << _childId << ", thread: " << _threadId << std::endl;
}
void start()
@@ -332,7 +346,6 @@ public:
queue.put("eof");
queueHandlerThread.join();
}
-
catch (Exception& exc)
{
std::cout << Util::logPrefix() + "Exception: " + exc.what() << std::endl;
@@ -345,6 +358,7 @@ public:
~Connection()
{
+ std::cout << Util::logPrefix() << "Closing connection in child: " << _childId << ", thread: " << _threadId << std::endl;
//_thread.stop();
}
@@ -449,7 +463,6 @@ void run_lok_main(const std::string &loSubPath, Poco::UInt64 _childId, const std
if ( aChar == '\r' && *pStart == '\n')
{
pStart++;
- //std::cout << Util::logPrefix() << "child receive: " << aMessage << std::endl;
StringTokenizer tokens(aMessage, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
if (tokens[0] == "search")
@@ -520,10 +533,11 @@ void run_lok_main(const std::string &loSubPath, Poco::UInt64 _childId, const std
}
}
-
// Destroy LibreOfficeKit
loKit->pClass->destroy(loKit);
+ std::cout << Util::logPrefix() << "loolkit finished OK!" << std::endl;
+
pthread_exit(0);
}
catch (Exception& exc)
@@ -534,8 +548,6 @@ void run_lok_main(const std::string &loSubPath, Poco::UInt64 _childId, const std
{
std::cout << Util::logPrefix() + "Exception: " + exc.what() << std::endl;
}
-
- std::cout << Util::logPrefix() << "loolkit finished OK!" << std::endl;
}
#ifndef LOOLKIT_NO_MAIN
@@ -547,6 +559,8 @@ int main(int argc, char** argv)
Poco::UInt64 _childId = 0;
std::string _pipe;
+ Log::initialize("kit");
+
for (int i = 1; i < argc; ++i)
{
char *cmd = argv[i];
diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp
index db59e76..b43908c 100644
--- a/loolwsd/LOOLSession.cpp
+++ b/loolwsd/LOOLSession.cpp
@@ -44,7 +44,6 @@
#include <Poco/ThreadLocal.h>
#include <Poco/URI.h>
#include <Poco/URIStreamOpener.h>
-#include <Poco/Util/Application.h>
#include <Poco/Exception.h>
#include <Poco/Net/NetException.h>
#include <Poco/Net/DialogSocket.h>
@@ -77,7 +76,6 @@ using Poco::ThreadLocal;
using Poco::UInt64;
using Poco::URI;
using Poco::URIStreamOpener;
-using Poco::Util::Application;
using Poco::Exception;
using Poco::Net::DialogSocket;
using Poco::Net::SocketAddress;
@@ -107,13 +105,18 @@ LOOLSession::LOOLSession(std::shared_ptr<WebSocket> ws, Kind kind) :
LOOLSession::~LOOLSession()
{
- std::cout << Util::logPrefix() << "LOOLSession dtor this=" << this << " " << _kind << std::endl;
+ std::cout << Util::logPrefix() << "loolsession dtor this=" << this << " " << _kind << std::endl;
if (_ws)
Util::shutdownWebSocket(*_ws);
}
void LOOLSession::sendTextFrame(const std::string& text)
{
+ if (!_ws)
+ Log::error("No socket to send to.");
+ else
+ Log::debug(_kindString + ",Send," + getAbbreviatedMessage(text.c_str(), text.size()));
+
std::unique_lock<std::mutex> lock(_mutex);
_ws->sendFrame(text.data(), text.size());
@@ -121,6 +124,11 @@ void LOOLSession::sendTextFrame(const std::string& text)
void LOOLSession::sendBinaryFrame(const char *buffer, int length)
{
+ if (!_ws)
+ Log::error("No socket to send to.");
+ else
+ Log::debug(_kindString + ",Send," + std::to_string(length) + " bytes");
+
std::unique_lock<std::mutex> lock(_mutex);
if (length > 1000)
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index 41da9bb..2bb61a1 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -251,25 +251,25 @@ namespace
caps = cap_get_proc();
if (caps == NULL)
{
- Application::instance().logger().error(Util::logPrefix() + "cap_get_proc() failed: " + strerror(errno));
+ Log::error(std::string("cap_get_proc() failed: ") + strerror(errno));
exit(1);
}
if (cap_set_flag(caps, CAP_EFFECTIVE, sizeof(cap_list)/sizeof(cap_list[0]), cap_list, CAP_CLEAR) == -1 ||
cap_set_flag(caps, CAP_PERMITTED, sizeof(cap_list)/sizeof(cap_list[0]), cap_list, CAP_CLEAR) == -1)
{
- Application::instance().logger().error(Util::logPrefix() + "cap_set_flag() failed: " + strerror(errno));
+ Log::error(std::string("cap_set_flag() failed: ") + strerror(errno));
exit(1);
}
if (cap_set_proc(caps) == -1)
{
- Application::instance().logger().error(std::string("cap_set_proc() failed: ") + strerror(errno));
+ Log::error(std::string("cap_set_proc() failed: ") + strerror(errno));
exit(1);
}
char *capText = cap_to_text(caps, NULL);
- Application::instance().logger().information(Util::logPrefix() + "Capabilities now: " + capText);
+ Log::info(std::string("Capabilities now: ") + capText);
cap_free(capText);
cap_free(caps);
@@ -283,7 +283,7 @@ namespace
// to do chroot().
if (setuid(getuid()) != 0)
{
- Application::instance().logger().error(std::string("setuid() failed: ") + strerror(errno));
+ Log::error(std::string("setuid() failed: ") + strerror(errno));
}
}
#if ENABLE_DEBUG
@@ -307,7 +307,7 @@ namespace
}
if (setuid(LOOLWSD::uid) != 0)
{
- Application::instance().logger().error(std::string("setuid() failed: ") + strerror(errno));
+ Log::error(std::string("setuid() failed: ") + strerror(errno));
}
}
#endif
@@ -608,7 +608,7 @@ public:
}
catch (WebSocketException& exc)
{
- Application::instance().logger().error(Util::logPrefix() + "RequestHandler::handleRequest(), WebSocketException: " + exc.message());
+ Log::error("RequestHandler::handleRequest(), WebSocketException: " + exc.message());
switch (exc.code())
{
case WebSocket::WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION:
@@ -626,7 +626,7 @@ public:
}
catch (IOException& exc)
{
- Application::instance().logger().error(Util::logPrefix() + "IOException: " + exc.message());
+ Log::error("IOException: " + exc.message());
}
}
};
@@ -651,7 +651,7 @@ public:
line += " / " + it->first + ": " + it->second;
}
- Application::instance().logger().information(line);
+ Log::info(line);
return new RequestHandler();
}
};
@@ -688,7 +688,7 @@ public:
}
catch (WebSocketException& exc)
{
- Application::instance().logger().error(Util::logPrefix() + "TestOutput::run(), WebSocketException: " + exc.message());
+ Log::error("TestOutput::run(), WebSocketException: " + exc.message());
_ws.close();
}
}
@@ -1223,7 +1223,7 @@ int LOOLWSD::createBroker()
const auto msg = Util::logPrefix() + "Launching broker: " + executable + " "
+ Poco::cat(std::string(" "), args.begin(), args.end());
- Application::instance().logger().information(msg);
+ Log::info(msg);
ProcessHandle child = Process::launch(executable, args);
@@ -1255,6 +1255,8 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
setSignals(false);
#endif
+ Log::initialize("brk");
+
if (access(cache.c_str(), R_OK | W_OK | X_OK) != 0)
{
std::cout << Util::logPrefix() << "Unable to access " << cache <<
@@ -1394,14 +1396,14 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
// Terminate child processes
for (auto i : MasterProcessSession::_childProcesses)
{
- logger().information(Util::logPrefix() + "Requesting child process " + std::to_string(i.first) + " to terminate");
+ Log::info("Requesting child process " + std::to_string(i.first) + " to terminate");
Process::requestTermination(i.first);
}
// wait broker process finish
waitpid(-1, &status, WUNTRACED);
- std::cout << Util::logPrefix() << "loolwsd finished OK!" << std::endl;
+ Log::info("loolwsd finished OK!");
return Application::EXIT_OK;
}
diff --git a/loolwsd/MasterProcessSession.cpp b/loolwsd/MasterProcessSession.cpp
index 513e200..2428b82 100644
--- a/loolwsd/MasterProcessSession.cpp
+++ b/loolwsd/MasterProcessSession.cpp
@@ -16,7 +16,6 @@
#include <Poco/Random.h>
#include <Poco/URI.h>
#include <Poco/URIStreamOpener.h>
-#include <Poco/Util/Application.h>
#include "LOOLProtocol.hpp"
#include "LOOLSession.hpp"
@@ -42,7 +41,6 @@ using Poco::StringTokenizer;
using Poco::Thread;
using Poco::UInt64;
using Poco::URI;
-using Poco::Util::Application;
std::map<Process::PID, UInt64> MasterProcessSession::_childProcesses;
@@ -73,7 +71,7 @@ MasterProcessSession::~MasterProcessSession()
bool MasterProcessSession::handleInput(const char *buffer, int length)
{
- Application::instance().logger().information(Util::logPrefix() + _kindString + ",Input," + getAbbreviatedMessage(buffer, length));
+ Log::info(_kindString + ",Recv," + getAbbreviatedMessage(buffer, length));
std::string firstLine = getFirstLine(buffer, length);
StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
@@ -609,7 +607,7 @@ void MasterProcessSession::dispatchChild()
}
catch (Exception& exc)
{
- Application::instance().logger().error( Util::logPrefix() +
+ Log::error(
"createDirectories(\"" + aDstPath.toString() + "\") failed: " + exc.displayText() );
}
@@ -620,11 +618,11 @@ void MasterProcessSession::dispatchChild()
aToCleanup.remove();
#ifdef __linux
- Application::instance().logger().information(Util::logPrefix() + "Linking " + aSrcFile.toString() + " to " + aDstFile.toString());
+ Log::info("Linking " + aSrcFile.toString() + " to " + aDstFile.toString());
if (!File(aDstFile).exists() && link(aSrcFile.toString().c_str(), aDstFile.toString().c_str()) == -1)
{
// Failed
- Application::instance().logger().error( Util::logPrefix() +
+ Log::error(
"link(\"" + aSrcFile.toString() + "\",\"" + aDstFile.toString() + "\") failed: " + strerror(errno) );
}
#endif
@@ -634,13 +632,13 @@ void MasterProcessSession::dispatchChild()
//fallback
if (!File(aDstFile).exists())
{
- Application::instance().logger().information(Util::logPrefix() + "Copying " + aSrcFile.toString() + " to " + aDstFile.toString());
+ Log::info(Util::logPrefix() + "Copying " + aSrcFile.toString() + " to " + aDstFile.toString());
File(aSrcFile).copyTo(aDstFile.toString());
}
}
catch (Exception& exc)
{
- Application::instance().logger().error( Util::logPrefix() +
+ Log::error(
"copyTo(\"" + aSrcFile.toString() + "\",\"" + aDstFile.toString() + "\") failed: " + exc.displayText());
}
}
@@ -654,10 +652,13 @@ void MasterProcessSession::dispatchChild()
void MasterProcessSession::forwardToPeer(const char *buffer, int length)
{
- Application::instance().logger().information(Util::logPrefix() + _kindString + ",forwardToPeer," + getAbbreviatedMessage(buffer, length));
+ Log::info(_kindString + ",forwardToPeer," + getAbbreviatedMessage(buffer, length));
auto peer = _peer.lock();
if (!peer)
+ {
+ Log::error("no peer to forward to");
return;
+ }
peer->sendBinaryFrame(buffer, length);
}
diff --git a/loolwsd/TileCache.cpp b/loolwsd/TileCache.cpp
index 3bd5939..56641c1 100644
--- a/loolwsd/TileCache.cpp
+++ b/loolwsd/TileCache.cpp
@@ -27,7 +27,6 @@
#include <Poco/StringTokenizer.h>
#include <Poco/Timestamp.h>
#include <Poco/URI.h>
-#include <Poco/Util/Application.h>
#include "LOOLWSD.hpp"
#include "LOOLProtocol.hpp"
@@ -42,7 +41,6 @@ using Poco::StringTokenizer;
using Poco::SyntaxException;
using Poco::Timestamp;
using Poco::URI;
-using Poco::Util::Application;
using namespace LOOLProtocol;
@@ -384,7 +382,7 @@ void TileCache::setup(const std::string& timestamp)
Timestamp::TimeVal lastTimeVal;
std::istringstream(timestamp) >> lastTimeVal;
lastModified = lastTimeVal;
- Application::instance().logger().information(Util::logPrefix() + "Timestamp provided externally: " + timestamp);
+ Log::info("Timestamp provided externally: " + timestamp);
cleanEverything = (getLastModified() < Timestamp(lastModified));
}
@@ -401,7 +399,7 @@ void TileCache::setup(const std::string& timestamp)
{
// document changed externally, clean up everything
cacheDir.remove(true);
- Application::instance().logger().information(Util::logPrefix() + "Completely cleared cache: " + toplevelCacheDirName());
+ Log::info("Completely cleared cache: " + toplevelCacheDirName());
}
else
{
@@ -410,7 +408,7 @@ void TileCache::setup(const std::string& timestamp)
if (editingCacheDir.exists())
{
editingCacheDir.remove(true);
- Application::instance().logger().information(Util::logPrefix() + "Cleared the editing cache: " + cacheDirName(true));
+ Log::info("Cleared the editing cache: " + cacheDirName(true));
}
}
}
diff --git a/loolwsd/Util.cpp b/loolwsd/Util.cpp
index 4ce1cd0..87dd14a 100644
--- a/loolwsd/Util.cpp
+++ b/loolwsd/Util.cpp
@@ -69,6 +69,38 @@ namespace rng
}
}
+namespace Log
+{
+ static std::string binname;
+
+ void initialize(const std::string& name)
+ {
+ binname = name;
+ auto& logger = Poco::Logger::get(name);
+ logger.information("Initializing " + name);
+ }
+
+ Poco::Logger& logger()
+ {
+ return Poco::Logger::get(binname);
+ }
+
+ void debug(const std::string& msg)
+ {
+ return logger().debug(Util::logPrefix() + msg);
+ }
+
+ void info(const std::string& msg)
+ {
+ logger().information(Util::logPrefix() + msg);
+ }
+
+ void error(const std::string& msg)
+ {
+ return logger().error(Util::logPrefix() + msg);
+ }
+}
+
namespace Util
{
static const Poco::Int64 epochStart = Poco::Timestamp().epochMicroseconds();
@@ -86,8 +118,10 @@ namespace Util
usec %= (one_s);
std::ostringstream stream;
- stream << Poco::Process::id() << "," << std::setw(2) << std::setfill('0') << (Poco::Thread::current() ? Poco::Thread::current()->id() : 0) << "," <<
- std::setw(2) << hours << ":" << std::setw(2) << minutes << ":" << std::setw(2) << seconds << "." << std::setw(6) << usec << ",";
+ stream << Log::binname << ',' << Poco::Process::id() << ',' << std::setw(2) << std::setfill('0')
+ << (Poco::Thread::current() ? Poco::Thread::current()->id() : 0) << ',' << std::setw(2) << ','
+ << hours << ':' << std::setw(2) << minutes << ':' << std::setw(2) << seconds << "." << std::setw(6) << usec
+ << ',';
return stream.str();
}
diff --git a/loolwsd/Util.hpp b/loolwsd/Util.hpp
index 8db7df3..8b1babf 100644
--- a/loolwsd/Util.hpp
+++ b/loolwsd/Util.hpp
@@ -13,6 +13,7 @@
#include <string>
#include <Poco/Net/WebSocket.h>
+#include <Poco/Logger.h>
#define LOK_USE_UNSTABLE_API
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
@@ -44,6 +45,17 @@ namespace Util
ssize_t readMessage(int nPipe, char* pBuffer, ssize_t nSize);
};
+//TODO: Move to own file.
+namespace Log
+{
+ void initialize(const std::string& name);
+ Poco::Logger& logger();
+
+ void debug(const std::string& msg);
+ void info(const std::string& msg);
+ void error(const std::string& msg);
+}
+
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 9de7ae80c38fc4a9008358f57b9e534f56e546c2
Author: Henry Castro <hcastro at collabora.com>
Date: Sun Dec 20 12:45:19 2015 -0500
loolwsd: merged systemplate-setup
Change-Id: Id066b02e405246d6a0a268aa1b29e09cd7730642
diff --git a/loolwsd/loolwsd-systemplate-setup b/loolwsd/loolwsd-systemplate-setup
index 627f230..c2f4483 100755
--- a/loolwsd/loolwsd-systemplate-setup
+++ b/loolwsd/loolwsd-systemplate-setup
@@ -6,6 +6,7 @@ test $# -eq 2 || { echo "Usage: $0 <chroot template directory for system libs to
CHROOT=$1
INSTDIR=$2
+POCODIR=/usr/local/lib
test -d "$INSTDIR" || { echo "No such directory: $INSTDIR"; exit 1; }
@@ -45,6 +46,9 @@ cd / || exit 1
lib/*-linux-gnu/libnss* \
-type l
+ find lib/libnss_* lib64/libnss_* -type l
+ find lib/*-linux-gnu/libnss* -type l
+
# Go through the LO shared objects and check what system libraries
# they link to.
find $INSTDIR -name '*.so' -o -name '*.so.[0-9]*' |
@@ -52,6 +56,14 @@ cd / || exit 1
ldd $file 2>/dev/null
done |
grep -v dynamic | cut -d " " -f 3 | grep -E '^(/lib|/usr)' | sort -u | sed -e 's,^/,,'
+
+ # Go through the loolkit
+ find $POCODIR -name '*Poco*.so' -o -name '*.so.[0-9]*' |
+ while read file; do
+ ldd $file 2>/dev/null
+ done |
+ grep -v dynamic | cut -d " " -f 3 | grep -E '^(/lib|/usr)' | sort -u | sed -e 's,^/,,'
+
else
find usr/lib/dyld \
usr/lib/*.dylib \
@@ -92,6 +104,67 @@ cd / || exit 1
cpio -p -d -L $CHROOT
mkdir -p $CHROOT/tmp
+mkdir -p $CHROOT/usr/bin/
+dummy=$CHROOT/usr/bin/dummy
+
+# checking for library containing Poco::Application
+cat <<_ACEOF >$dummy.cpp
+#include <iostream>
+#include <Poco/Util/Application.h>
+
+using Poco::Util::Application;
+
+int main ()
+{
+ std::cout << "Poco functionality OK!" << std::endl;
+ return Application::EXIT_OK;
+}
+_ACEOF
+
+gcc_compile='g++ -o $dummy.o -c $dummy.cpp'
+(eval "$gcc_compile") 2>$dummy.err
+
+if ! test $? = 0; then
+ cat $dummy.err;
+ exit 1;
+fi
+
+gcc_link='g++ -o $dummy -lcap -lpng -ldl -lPocoNet -lPocoUtil -lPocoXML -lPocoJSON -lPocoFoundation $dummy.o'
+(eval "$gcc_link") 2>$dummy.err
+
+if ! test $? = 0; then
+ cat $dummy.err;
+ exit 1;
+fi
+
+lib_poco=$( echo "$dummy" |
+ while read file; do
+ ldd $file 2>/dev/null
+ done |
+ grep -v dynamic | cut -d " " -f 3 | grep -E '^(/lib|/usr)')
+
+for lib in $lib_poco
+do
+ cp --parent -n $lib $CHROOT
+
+ libs=$( echo $lib |
+ while read file; do
+ ldd $file 2>/dev/null
+ done |
+ grep -v dynamic | cut -d " " -f 3 | grep -E '^(/lib|/usr)')
+
+ for sofile in $libs
+ do
+ cp --parent -n $sofile $CHROOT
+ done
+done
+
+loaders="$(find /lib/ld-* -type l) $(find /lib32/ld-* -type l) $(find /lib64/ld-* -type l)"
+
+for loader in $loaders
+do
+ cp --parent -n $loader $CHROOT
+done
# /usr/share/fonts needs to be taken care of separately because the
# directory time stamps must be preserved are for fontconfig to trust
@@ -108,3 +181,6 @@ if [ `uname -s` = Linux ]; then
cp -r -p /usr/share/ghostscript/fonts usr/share/ghostscript
fi
fi
+
+echo "testing if Poco libraries were installed properly"
+sudo chroot $CHROOT /usr/bin/dummy
commit 3d0daa2f8855ff2a87785ea7a2c9e0a54288a855
Author: Henry Castro <hcastro at collabora.com>
Date: Sat Dec 19 20:09:48 2015 -0500
loolwsd: deligating to loolbroker and loolkit
Change-Id: I8499540630373a1bee12a5f58fca3ed701ff6404
diff --git a/loolwsd/ChildProcessSession.cpp b/loolwsd/ChildProcessSession.cpp
index 95909af..b74138b 100644
--- a/loolwsd/ChildProcessSession.cpp
+++ b/loolwsd/ChildProcessSession.cpp
@@ -139,10 +139,16 @@ bool ChildProcessSession::handleInput(const char *buffer, int length)
tokens[0] == "resetselection" ||
tokens[0] == "saveas");
- if (_docType != "text" && _loKitDocument->pClass->getPart(_loKitDocument) != _clientPart)
{
- _loKitDocument->pClass->setPart(_loKitDocument, _clientPart);
+ Poco::Mutex::ScopedLock lock(_mutex);
+
+ _loKitDocument->pClass->setView(_loKitDocument, _viewId);
+ if (_docType != "text" && _loKitDocument->pClass->getPart(_loKitDocument) != _clientPart)
+ {
+ _loKitDocument->pClass->setPart(_loKitDocument, _clientPart);
+ }
}
+
if (tokens[0] == "clientzoom")
{
return clientZoom(buffer, length, tokens);
diff --git a/loolwsd/LOOLBroker.cpp b/loolwsd/LOOLBroker.cpp
index df77fa8..5a64598 100644
--- a/loolwsd/LOOLBroker.cpp
+++ b/loolwsd/LOOLBroker.cpp
@@ -701,16 +701,16 @@ int main(int argc, char** argv)
const Poco::UInt64 _childId = Util::rng::getNext();
- Path jail = Path::forDirectory(childRoot + Path::separator() + std::to_string(_childId));
- File(jail).createDirectories();
+ Path jailPath = Path::forDirectory(childRoot + Path::separator() + std::to_string(_childId));
+ File(jailPath).createDirectories();
- Path jailLOInstallation(jail, loSubPath);
+ Path jailLOInstallation(jailPath, loSubPath);
jailLOInstallation.makeDirectory();
File(jailLOInstallation).createDirectory();
// Copy (link) LO installation and other necessary files into it from the template
- linkOrCopy(sysTemplate, jail);
+ linkOrCopy(sysTemplate, jailPath);
linkOrCopy(loTemplate, jailLOInstallation);
// It is necessary to deploy loolkit process to chroot jail.
@@ -719,34 +719,45 @@ int main(int argc, char** argv)
std::cout << Util::logPrefix() << "loolkit does not exists" << std::endl;
exit(-1);
}
- File("loolkit").copyTo(Path(jail, "/usr/bin").toString());
+ File("loolkit").copyTo(Path(jailPath, "/usr/bin").toString());
+
+ // We need this because sometimes the hostname is not resolved
+ std::vector<std::string> networkFiles = {"/etc/host.conf", "/etc/hosts", "/etc/nsswitch.conf", "/etc/resolv.conf"};
+ for (std::vector<std::string>::iterator it = networkFiles.begin(); it != networkFiles.end(); ++it)
+ {
+ File networkFile(*it);
+ if (networkFile.exists())
+ {
+ networkFile.copyTo(Path(jailPath, "/etc").toString());
+ }
+ }
#ifdef __linux
// Create the urandom and random devices
- File(Path(jail, "/dev")).createDirectory();
- if (mknod((jail.toString() + "/dev/random").c_str(),
+ File(Path(jailPath, "/dev")).createDirectory();
+ if (mknod((jailPath.toString() + "/dev/random").c_str(),
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
makedev(1, 8)) != 0)
{
std::cout << Util::logPrefix() +
- "mknod(" + jail.toString() + "/dev/random) failed: " +
+ "mknod(" + jailPath.toString() + "/dev/random) failed: " +
strerror(errno) << std::endl;
}
- if (mknod((jail.toString() + "/dev/urandom").c_str(),
+ if (mknod((jailPath.toString() + "/dev/urandom").c_str(),
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
makedev(1, 9)) != 0)
{
std::cout << Util::logPrefix() +
- "mknod(" + jail.toString() + "/dev/urandom) failed: " +
+ "mknod(" + jailPath.toString() + "/dev/urandom) failed: " +
strerror(errno) << std::endl;
}
#endif
- std::cout << Util::logPrefix() << "loolbroker -> chroot(\"" + jail.toString() + "\")" << std::endl;
- if (chroot(jail.toString().c_str()) == -1)
+ std::cout << Util::logPrefix() << "loolbroker -> chroot(\"" + jailPath.toString() + "\")" << std::endl;
+ if (chroot(jailPath.toString().c_str()) == -1)
{
- std::cout << Util::logPrefix() << "chroot(\"" + jail.toString() + "\") failed: " + strerror(errno) << std::endl;
+ std::cout << Util::logPrefix() << "chroot(\"" + jailPath.toString() + "\") failed: " + strerror(errno) << std::endl;
exit(-1);
}
@@ -758,6 +769,8 @@ int main(int argc, char** argv)
#ifdef __linux
dropCapability(CAP_SYS_CHROOT);
+ dropCapability(CAP_MKNOD);
+ dropCapability(CAP_FOWNER);
#else
dropCapability();
#endif
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index 229f78d..41da9bb 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -148,8 +148,172 @@ using Poco::Net::Socket;
using Poco::ThreadLocal;
using Poco::Random;
using Poco::NamedMutex;
+using Poco::ProcessHandle;
using Poco::URI;
+namespace
+{
+ ThreadLocal<std::string> sourceForLinkOrCopy;
+ ThreadLocal<Path> destinationForLinkOrCopy;
+
+ int linkOrCopyFunction(const char *fpath,
+ const struct stat* /*sb*/,
+ int typeflag,
+ struct FTW* /*ftwbuf*/)
+ {
+ if (strcmp(fpath, sourceForLinkOrCopy->c_str()) == 0)
+ return 0;
+
+ assert(fpath[strlen(sourceForLinkOrCopy->c_str())] == '/');
+ const char *relativeOldPath = fpath + strlen(sourceForLinkOrCopy->c_str()) + 1;
+
+#ifdef __APPLE__
+ if (strcmp(relativeOldPath, "PkgInfo") == 0)
+ return 0;
+#endif
+
+ Path newPath(*destinationForLinkOrCopy, Path(relativeOldPath));
+
+ switch (typeflag)
+ {
+ case FTW_F:
+ File(newPath.parent()).createDirectories();
+ if (link(fpath, newPath.toString().c_str()) == -1)
+ {
+ Application::instance().logger().error(Util::logPrefix() +
+ "link(\"" + fpath + "\",\"" + newPath.toString() + "\") failed: " +
+ strerror(errno));
+ exit(1);
+ }
+ break;
+ case FTW_DP:
+ {
+ struct stat st;
+ if (stat(fpath, &st) == -1)
+ {
+ Application::instance().logger().error(Util::logPrefix() +
+ "stat(\"" + fpath + "\") failed: " +
+ strerror(errno));
+ return 1;
+ }
+ File(newPath).createDirectories();
+ struct utimbuf ut;
+ ut.actime = st.st_atime;
+ ut.modtime = st.st_mtime;
+ if (utime(newPath.toString().c_str(), &ut) == -1)
+ {
+ Application::instance().logger().error(Util::logPrefix() +
+ "utime(\"" + newPath.toString() + "\", &ut) failed: " +
+ strerror(errno));
+ return 1;
+ }
+ }
+ break;
+ case FTW_DNR:
+ Application::instance().logger().error(Util::logPrefix() +
+ "Cannot read directory '" + fpath + "'");
+ return 1;
+ case FTW_NS:
+ Application::instance().logger().error(Util::logPrefix() +
+ "nftw: stat failed for '" + fpath + "'");
+ return 1;
+ case FTW_SLN:
+ Application::instance().logger().information(Util::logPrefix() +
+ "nftw: symlink to nonexistent file: '" + fpath + "', ignored");
+ break;
+ default:
+ assert(false);
+ }
+ return 0;
+ }
+
+ void linkOrCopy(const std::string& source, const Path& destination)
+ {
+ *sourceForLinkOrCopy = source;
+ if (sourceForLinkOrCopy->back() == '/')
+ sourceForLinkOrCopy->pop_back();
+ *destinationForLinkOrCopy = destination;
+ if (nftw(source.c_str(), linkOrCopyFunction, 10, FTW_DEPTH) == -1)
+ Application::instance().logger().error(Util::logPrefix() +
+ "linkOrCopy: nftw() failed for '" + source + "'");
+ }
+
+ void dropCapability(
+#ifdef __linux
+ cap_value_t capability
+#endif
+ )
+ {
+#ifdef __linux
+ cap_t caps;
+ cap_value_t cap_list[] = { capability };
+
+ caps = cap_get_proc();
+ if (caps == NULL)
+ {
+ Application::instance().logger().error(Util::logPrefix() + "cap_get_proc() failed: " + strerror(errno));
+ exit(1);
+ }
+
+ if (cap_set_flag(caps, CAP_EFFECTIVE, sizeof(cap_list)/sizeof(cap_list[0]), cap_list, CAP_CLEAR) == -1 ||
+ cap_set_flag(caps, CAP_PERMITTED, sizeof(cap_list)/sizeof(cap_list[0]), cap_list, CAP_CLEAR) == -1)
+ {
+ Application::instance().logger().error(Util::logPrefix() + "cap_set_flag() failed: " + strerror(errno));
+ exit(1);
+ }
+
+ if (cap_set_proc(caps) == -1)
+ {
+ Application::instance().logger().error(std::string("cap_set_proc() failed: ") + strerror(errno));
+ exit(1);
+ }
+
+ char *capText = cap_to_text(caps, NULL);
+ Application::instance().logger().information(Util::logPrefix() + "Capabilities now: " + capText);
+ cap_free(capText);
+
+ cap_free(caps);
+#endif
+ // We assume that on non-Linux we don't need to be root to be able to hardlink to files we
+ // don't own, so drop root.
+ if (geteuid() == 0 && getuid() != 0)
+ {
+ // The program is setuid root. Not normal on Linux where we use setcap, but if this
+ // needs to run on non-Linux Unixes, setuid root is what it will bneed to be to be able
+ // to do chroot().
+ if (setuid(getuid()) != 0)
+ {
+ Application::instance().logger().error(std::string("setuid() failed: ") + strerror(errno));
+ }
+ }
+#if ENABLE_DEBUG
+ if (geteuid() == 0 && getuid() == 0)
+ {
+#ifdef __linux
+ // Argh, awful hack
+ if (capability == CAP_FOWNER)
+ return;
+#endif
+
+ // Running under sudo, probably because being debugged? Let's drop super-user rights.
+ LOOLWSD::runningAsRoot = true;
+ if (LOOLWSD::uid == 0)
+ {
+ struct passwd *nobody = getpwnam("nobody");
+ if (nobody)
+ LOOLWSD::uid = nobody->pw_uid;
+ else
+ LOOLWSD::uid = 65534;
+ }
+ if (setuid(LOOLWSD::uid) != 0)
+ {
+ Application::instance().logger().error(std::string("setuid() failed: ") + strerror(errno));
+ }
+ }
+#endif
+ }
+}
+
class QueueHandler: public Runnable
{
public:
@@ -391,7 +555,7 @@ public:
do
{
- char buffer[200000];
+ char buffer[200000]; //FIXME: Dynamic?
if ((pollTimeout = ws->poll(waitTime, Socket::SELECT_READ)))
{
@@ -752,169 +916,6 @@ void LOOLWSD::displayHelp()
helpFormatter.format(std::cout);
}
-namespace
-{
- ThreadLocal<std::string> sourceForLinkOrCopy;
- ThreadLocal<Path> destinationForLinkOrCopy;
-
- int linkOrCopyFunction(const char *fpath,
- const struct stat* /*sb*/,
- int typeflag,
- struct FTW* /*ftwbuf*/)
- {
- if (strcmp(fpath, sourceForLinkOrCopy->c_str()) == 0)
- return 0;
-
- assert(fpath[strlen(sourceForLinkOrCopy->c_str())] == '/');
- const char *relativeOldPath = fpath + strlen(sourceForLinkOrCopy->c_str()) + 1;
-
-#ifdef __APPLE__
- if (strcmp(relativeOldPath, "PkgInfo") == 0)
- return 0;
-#endif
-
- Path newPath(*destinationForLinkOrCopy, Path(relativeOldPath));
-
- switch (typeflag)
- {
- case FTW_F:
- File(newPath.parent()).createDirectories();
- if (link(fpath, newPath.toString().c_str()) == -1)
- {
- Application::instance().logger().error(Util::logPrefix() +
- "link(\"" + fpath + "\",\"" + newPath.toString() + "\") failed: " +
- strerror(errno));
- exit(1);
- }
- break;
- case FTW_DP:
- {
- struct stat st;
- if (stat(fpath, &st) == -1)
- {
- Application::instance().logger().error(Util::logPrefix() +
- "stat(\"" + fpath + "\") failed: " +
- strerror(errno));
- return 1;
- }
- File(newPath).createDirectories();
- struct utimbuf ut;
- ut.actime = st.st_atime;
- ut.modtime = st.st_mtime;
- if (utime(newPath.toString().c_str(), &ut) == -1)
- {
- Application::instance().logger().error(Util::logPrefix() +
- "utime(\"" + newPath.toString() + "\", &ut) failed: " +
- strerror(errno));
- return 1;
- }
- }
- break;
- case FTW_DNR:
- Application::instance().logger().error(Util::logPrefix() +
- "Cannot read directory '" + fpath + "'");
- return 1;
- case FTW_NS:
- Application::instance().logger().error(Util::logPrefix() +
- "nftw: stat failed for '" + fpath + "'");
- return 1;
- case FTW_SLN:
- Application::instance().logger().information(Util::logPrefix() +
- "nftw: symlink to nonexistent file: '" + fpath + "', ignored");
- break;
- default:
- assert(false);
- }
- return 0;
- }
-
- void linkOrCopy(const std::string& source, const Path& destination)
- {
- *sourceForLinkOrCopy = source;
- if (sourceForLinkOrCopy->back() == '/')
- sourceForLinkOrCopy->pop_back();
- *destinationForLinkOrCopy = destination;
- if (nftw(source.c_str(), linkOrCopyFunction, 10, FTW_DEPTH) == -1)
- Application::instance().logger().error(Util::logPrefix() +
- "linkOrCopy: nftw() failed for '" + source + "'");
- }
-
- void dropCapability(
-#ifdef __linux
- cap_value_t capability
-#endif
- )
- {
-#ifdef __linux
- cap_t caps;
- cap_value_t cap_list[] = { capability };
-
- caps = cap_get_proc();
- if (caps == NULL)
- {
- Application::instance().logger().error(Util::logPrefix() + "cap_get_proc() failed: " + strerror(errno));
- exit(1);
- }
-
- if (cap_set_flag(caps, CAP_EFFECTIVE, sizeof(cap_list)/sizeof(cap_list[0]), cap_list, CAP_CLEAR) == -1 ||
- cap_set_flag(caps, CAP_PERMITTED, sizeof(cap_list)/sizeof(cap_list[0]), cap_list, CAP_CLEAR) == -1)
- {
- Application::instance().logger().error(Util::logPrefix() + "cap_set_flag() failed: " + strerror(errno));
- exit(1);
- }
-
- if (cap_set_proc(caps) == -1)
- {
- Application::instance().logger().error(std::string("cap_set_proc() failed: ") + strerror(errno));
- exit(1);
- }
-
- char *capText = cap_to_text(caps, NULL);
- Application::instance().logger().information(Util::logPrefix() + "Capabilities now: " + capText);
- cap_free(capText);
-
- cap_free(caps);
-#endif
- // We assume that on non-Linux we don't need to be root to be able to hardlink to files we
- // don't own, so drop root.
- if (geteuid() == 0 && getuid() != 0)
- {
- // The program is setuid root. Not normal on Linux where we use setcap, but if this
- // needs to run on non-Linux Unixes, setuid root is what it will bneed to be to be able
- // to do chroot().
- if (setuid(getuid()) != 0)
- {
- Application::instance().logger().error(std::string("setuid() failed: ") + strerror(errno));
- }
- }
-#if ENABLE_DEBUG
- if (geteuid() == 0 && getuid() == 0)
- {
-#ifdef __linux
- // Argh, awful hack
- if (capability == CAP_FOWNER)
- return;
-#endif
-
- // Running under sudo, probably because being debugged? Let's drop super-user rights.
- LOOLWSD::runningAsRoot = true;
- if (LOOLWSD::uid == 0)
- {
- struct passwd *nobody = getpwnam("nobody");
- if (nobody)
- LOOLWSD::uid = nobody->pw_uid;
- else
- LOOLWSD::uid = 65534;
- }
- if (setuid(LOOLWSD::uid) != 0)
- {
- Application::instance().logger().error(std::string("setuid() failed: ") + strerror(errno));
- }
- }
-#endif
- }
-}
-
// Writer, Impress or Calc
void LOOLWSD::componentMain()
{
@@ -1208,11 +1209,34 @@ int LOOLWSD::createDesktop()
return Application::EXIT_OK;
}
-void LOOLWSD::startupDesktop(int nDesktops)
+int LOOLWSD::createBroker()
{
- for (int nCntr = nDesktops; nCntr; nCntr--)
+ Process::Args args;
+
+ args.push_back("--losubpath=" + LOOLWSD::loSubPath);
+ args.push_back("--systemplate=" + sysTemplate);
+ args.push_back("--lotemplate=" + loTemplate);
+ args.push_back("--childroot=" + childRoot);
+ args.push_back("--numprespawns=" + std::to_string(_numPreSpawnedChildren));
+
+ std::string executable = Path(Application::instance().commandPath()).parent().toString() + "loolbroker";
+
+ const auto msg = Util::logPrefix() + "Launching broker: " + executable + " "
+ + Poco::cat(std::string(" "), args.begin(), args.end());
+ Application::instance().logger().information(msg);
+
+ ProcessHandle child = Process::launch(executable, args);
+
+ MasterProcessSession::_childProcesses[child.id()] = child.id();
+
+ return Application::EXIT_OK;
+}
+
+void LOOLWSD::startupBroker(const signed nBrokers)
+{
+ for (signed nCntr = nBrokers; nCntr > 0; --nCntr)
{
- if (createDesktop() < 0)
+ if (createBroker() < 0)
break;
}
}
@@ -1274,7 +1298,7 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
_namedMutexLOOL.lock();
- startupDesktop(1);
+ startupBroker(1);
#ifdef __linux
dropCapability(CAP_SYS_CHROOT);
@@ -1299,6 +1323,12 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
srv2.start();
+ if ( (writerBroker = open(FIFO_FILE.c_str(), O_WRONLY) ) < 0 )
+ {
+ std::cout << Util::logPrefix() << "Pipe opened for writing" << strerror(errno) << std::endl;
+ return Application::EXIT_UNAVAILABLE;
+ }
+
_namedMutexLOOL.unlock();
TestInput input(*this, svs, srv);
@@ -1361,9 +1391,12 @@ int LOOLWSD::main(const std::vector<std::string>& /*args*/)
threadPool.joinAll();
threadPool2.joinAll();
- // Clear sessions to pre-spawned child processes that have connected
- // but are not yet assigned a document to work on.
- MasterProcessSession::_availableChildSessions.clear();
+ // Terminate child processes
+ for (auto i : MasterProcessSession::_childProcesses)
+ {
+ logger().information(Util::logPrefix() + "Requesting child process " + std::to_string(i.first) + " to terminate");
+ Process::requestTermination(i.first);
+ }
// wait broker process finish
waitpid(-1, &status, WUNTRACED);
diff --git a/loolwsd/LOOLWSD.hpp b/loolwsd/LOOLWSD.hpp
index 637c246..3f7cfee 100644
--- a/loolwsd/LOOLWSD.hpp
+++ b/loolwsd/LOOLWSD.hpp
@@ -75,6 +75,9 @@ private:
int createComponent();
int createDesktop();
+ void startupBroker(int nBroker);
+ int createBroker();
+
#if ENABLE_DEBUG
public:
diff --git a/loolwsd/MasterProcessSession.cpp b/loolwsd/MasterProcessSession.cpp
index fb4af0b..513e200 100644
--- a/loolwsd/MasterProcessSession.cpp
+++ b/loolwsd/MasterProcessSession.cpp
@@ -46,7 +46,7 @@ using Poco::Util::Application;
std::map<Process::PID, UInt64> MasterProcessSession::_childProcesses;
-std::set<std::shared_ptr<MasterProcessSession>> MasterProcessSession::_availableChildSessions;
+std::map<Thread::TID, std::shared_ptr<MasterProcessSession>> MasterProcessSession::_availableChildSessions;
std::mutex MasterProcessSession::_availableChildSessionMutex;
std::condition_variable MasterProcessSession::_availableChildSessionCV;
@@ -202,17 +202,19 @@ bool MasterProcessSession::handleInput(const char *buffer, int length)
sendTextFrame("error: cmd=child kind=invalid");
return false;
}
- if (tokens.count() != 3)
+ if (tokens.count() != 4)
{
sendTextFrame("error: cmd=child kind=syntax");
return false;
}
UInt64 childId = std::stoull(tokens[1]);
- Process::PID pidChild = std::stoull(tokens[2]);
+ Thread::TID tId = std::stoull(tokens[2]);
+ Process::PID pidChild = std::stoull(tokens[3]);
std::unique_lock<std::mutex> lock(_availableChildSessionMutex);
- _availableChildSessions.insert(shared_from_this());
+ _availableChildSessions.insert(std::pair<Thread::TID, std::shared_ptr<MasterProcessSession>> (tId, shared_from_this()));
+ std::cout << Util::logPrefix() << _kindString << ",Inserted " << this << " id=" << childId << " into _availableChildSessions, size=" << _availableChildSessions.size() << std::endl;
std::cout << Util::logPrefix() << "Inserted " << this << " id=" << childId << " into _availableChildSessions, size=" << _availableChildSessions.size() << std::endl;
_childId = childId;
_pidChild = pidChild;
@@ -543,30 +545,48 @@ void MasterProcessSession::sendTile(const char *buffer, int length, StringTokeni
void MasterProcessSession::dispatchChild()
{
+ short nRequest = 3;
+ bool bFound = false;
+
// Copy document into jail using the fixed name
std::shared_ptr<MasterProcessSession> childSession;
std::unique_lock<std::mutex> lock(_availableChildSessionMutex);
- std::cout << Util::logPrefix() << "_availableChildSessions size=" << _availableChildSessions.size() << std::endl;
+ std::cout << Util::logPrefix() << "waiting for a child session permission for " << Thread::currentTid() << std::endl;
+ while (nRequest-- && !bFound)
+ {
+ _availableChildSessionCV.wait_for(
+ lock,
+ std::chrono::milliseconds(2000),
+ [&bFound]
+ {
+ return (bFound = _availableChildSessions.find(Thread::currentTid()) != _availableChildSessions.end());
+ });
+
+ if (!bFound)
+ {
+ std::cout << Util::logPrefix() << "trying ..." << nRequest << std::endl;
+ // request again new URL session
+ std::string aMessage = "request " + std::to_string(Thread::currentTid()) + " " + _docURL + "\r\n";
+ Util::writeFIFO(LOOLWSD::writerBroker, aMessage.c_str(), aMessage.length());
+ }
+ }
- if (_availableChildSessions.size() == 0)
+ if ( bFound )
{
- std::cout << Util::logPrefix() << "waiting for a child session to become available" << std::endl;
- _availableChildSessionCV.wait(lock, [] { return _availableChildSessions.size() > 0; });
- std::cout << Util::logPrefix() << "waiting done" << std::endl;
+ std::cout << Util::logPrefix() << "waiting child session permission, done!" << std::endl;
+ childSession = _availableChildSessions[Thread::currentTid()];
+ _availableChildSessions.erase(Thread::currentTid());
}
- childSession = *(_availableChildSessions.begin());
- _availableChildSessions.erase(childSession);
lock.unlock();
- if (_availableChildSessions.size() == 0 && !LOOLWSD::doTest)
+ if ( !nRequest && !bFound )
{
- LOOLWSD::_namedMutexLOOL.lock();
- std::cout << Util::logPrefix() << "No available child sessions, queue new child session" << std::endl;
- LOOLWSD::_sharedForkChild.begin()[0] = LOOLWSD::_numPreSpawnedChildren;
- LOOLWSD::_namedMutexLOOL.unlock();
+ // it cannot get connected. shutdown.
+ Util::shutdownWebSocket(*_ws);
+ return;
}
// Assume a valid URI
diff --git a/loolwsd/MasterProcessSession.hpp b/loolwsd/MasterProcessSession.hpp
index ec5ff0d..4b9329a 100644
--- a/loolwsd/MasterProcessSession.hpp
+++ b/loolwsd/MasterProcessSession.hpp
@@ -42,10 +42,6 @@ public:
*/
std::string getSaveAs();
- // Sessions to pre-spawned child processes that have connected but are not yet assigned a
- // document to work on.
- static std::set<std::shared_ptr<MasterProcessSession>> _availableChildSessions;
-
protected:
bool invalidateTiles(const char *buffer, int length, Poco::StringTokenizer& tokens);
@@ -67,6 +63,9 @@ public:
// per document being edited (i.e., per child process).
std::weak_ptr<MasterProcessSession> _peer;
+ // Sessions to pre-spawned child processes that have connected but are not yet assigned a
+ // document to work on.
+ static std::map<Poco::Thread::TID, std::shared_ptr<MasterProcessSession>> _availableChildSessions;
static std::mutex _availableChildSessionMutex;
static std::condition_variable _availableChildSessionCV;
commit 236d0699b38b337ce280cc0a0728e5d25e80b3ac
Author: Henry Castro <hcastro at collabora.com>
Date: Sat Dec 19 17:20:04 2015 -0500
loolwsd: LOOLBroker process added
Change-Id: Ia7332761766026599b8ef415652874371938d311
diff --git a/loolwsd/.gitignore b/loolwsd/.gitignore
index 2054b6a..1461eea 100644
--- a/loolwsd/.gitignore
+++ b/loolwsd/.gitignore
@@ -32,6 +32,7 @@ lokitclient
loadtest
loolwsd
loolkit
+loolbroker
sockettransporttest
# Debug output
diff --git a/loolwsd/LOOLBroker.cpp b/loolwsd/LOOLBroker.cpp
new file mode 100644
index 0000000..df77fa8
--- /dev/null
+++ b/loolwsd/LOOLBroker.cpp
@@ -0,0 +1,860 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/capability.h>
+
+#include <utime.h>
+#include <ftw.h>
+#include <unistd.h>
+#include <dlfcn.h>
+
+#include <mutex>
+#include <cstring>
+#include <cassert>
+#include <iostream>
+#include <fstream>
+#include <deque>
+
+#include <Poco/Types.h>
+#include <Poco/Random.h>
+#include <Poco/Path.h>
+#include <Poco/File.h>
+#include <Poco/ThreadLocal.h>
+#include <Poco/Process.h>
+#include <Poco/Thread.h>
+#include <Poco/NamedMutex.h>
+
+#include "Util.hpp"
+
+// First include the grist of the helper process - ideally
+// we can avoid execve and share lots of memory here. We
+// can't link to a non-PIC translation unit though, so
+// include to share.
+#define LOOLKIT_NO_MAIN 1
+#include "LOOLKit.cpp"
+
+#define INTERVAL_PROBES 10
+#define MAINTENANCE_INTERVAL 1
+
+#define LIB_SOFFICEAPP "lib" "sofficeapp" ".so"
+#define LIB_SCLO "lib" "sclo" ".so"
+#define LIB_SWLO "lib" "swlo" ".so"
+#define LIB_SDLO "lib" "sdlo" ".so"
+
+typedef int (LokHookPreInit) ( const char *install_path, const char *user_profile_path );
+
+using Poco::Path;
+using Poco::File;
+using Poco::ThreadLocal;
+using Poco::Process;
+using Poco::Thread;
+using Poco::ProcessHandle;
+
+const std::string FIFO_FILE = "/tmp/loolwsdfifo";
+const std::string FIFO_BROKER = "/tmp/loolbroker.fifo";
+const std::string BROKER_SUFIX = ".fifo";
+const std::string BROKER_PREFIX = "/tmp/lokit";
+
+static int readerChild = -1;
+static int readerBroker = -1;
+static int timeoutCounter = 0;
+
+static unsigned int forkCounter = 0;
+static unsigned int childCounter = 0;
+
+static std::mutex forkMutex;
+static std::deque<Process::PID> _emptyURL;
+static std::map<Process::PID, int> _childProcesses;
+static std::map<std::string, Process::PID> _cacheURL;
+
+Poco::NamedMutex _namedMutexLOOL("loolwsd");
+
+namespace
+{
+ ThreadLocal<std::string> sourceForLinkOrCopy;
+ ThreadLocal<Path> destinationForLinkOrCopy;
+
+ int linkOrCopyFunction(const char *fpath,
+ const struct stat* /*sb*/,
+ int typeflag,
+ struct FTW* /*ftwbuf*/)
+ {
+ if (strcmp(fpath, sourceForLinkOrCopy->c_str()) == 0)
+ return 0;
+
+ assert(fpath[strlen(sourceForLinkOrCopy->c_str())] == '/');
+ const char *relativeOldPath = fpath + strlen(sourceForLinkOrCopy->c_str()) + 1;
+
+#ifdef __APPLE__
+ if (strcmp(relativeOldPath, "PkgInfo") == 0)
+ return 0;
+#endif
+
+ Path newPath(*destinationForLinkOrCopy, Path(relativeOldPath));
+
+ switch (typeflag)
+ {
+ case FTW_F:
+ File(newPath.parent()).createDirectories();
+ if (link(fpath, newPath.toString().c_str()) == -1)
+ {
+ std::cout << Util::logPrefix() +
+ "link(\"" + fpath + "\",\"" + newPath.toString() + "\") failed: " +
+ strerror(errno) << std::endl;
+ exit(1);
+ }
+ break;
+ case FTW_DP:
+ {
+ struct stat st;
+ if (stat(fpath, &st) == -1)
+ {
+ std::cout << Util::logPrefix() +
+ "stat(\"" + fpath + "\") failed: " +
+ strerror(errno) << std::endl;
+ return 1;
+ }
+ File(newPath).createDirectories();
+ struct utimbuf ut;
+ ut.actime = st.st_atime;
+ ut.modtime = st.st_mtime;
+ if (utime(newPath.toString().c_str(), &ut) == -1)
+ {
+ std::cout << Util::logPrefix() +
+ "utime(\"" + newPath.toString() + "\", &ut) failed: " +
+ strerror(errno) << std::endl;
+ return 1;
+ }
+ }
+ break;
+ case FTW_DNR:
+ std::cout <<Util::logPrefix() +
+ "Cannot read directory '" + fpath + "'" << std::endl;
+ return 1;
+ case FTW_NS:
+ std::cout <<Util::logPrefix() +
+ "nftw: stat failed for '" + fpath + "'" << std::endl;
+ return 1;
+ case FTW_SLN:
+ std::cout <<Util::logPrefix() +
+ "nftw: symlink to nonexistent file: '" + fpath + "', ignored" << std::endl;
+ break;
+ default:
+ assert(false);
+ }
+ return 0;
+ }
+
+ void linkOrCopy(const std::string& source, const Path& destination)
+ {
+ *sourceForLinkOrCopy = source;
+ if (sourceForLinkOrCopy->back() == '/')
+ sourceForLinkOrCopy->pop_back();
+ *destinationForLinkOrCopy = destination;
+ if (nftw(source.c_str(), linkOrCopyFunction, 10, FTW_DEPTH) == -1)
+ std::cout << Util::logPrefix() +
+ "linkOrCopy: nftw() failed for '" + source + "'" << std::endl;
+ }
+
+ void dropCapability(
+#ifdef __linux
+ cap_value_t capability
+#endif
+ )
+ {
+#ifdef __linux
+ cap_t caps;
+ cap_value_t cap_list[] = { capability };
+
+ caps = cap_get_proc();
+ if (caps == NULL)
+ {
+ std::cout << Util::logPrefix() + "cap_get_proc() failed: " + strerror(errno) << std::endl;
+ exit(1);
+ }
+
+ if (cap_set_flag(caps, CAP_EFFECTIVE, sizeof(cap_list)/sizeof(cap_list[0]), cap_list, CAP_CLEAR) == -1 ||
+ cap_set_flag(caps, CAP_PERMITTED, sizeof(cap_list)/sizeof(cap_list[0]), cap_list, CAP_CLEAR) == -1)
+ {
+ std::cout << Util::logPrefix() + "cap_set_flag() failed: " + strerror(errno) << std::endl;
+ exit(1);
+ }
+
+ if (cap_set_proc(caps) == -1)
+ {
+ std::cout << Util::logPrefix() << std::string("cap_set_proc() failed: ") + strerror(errno) << std::endl;
+ exit(1);
+ }
+
+ char *capText = cap_to_text(caps, NULL);
+ std::cout << Util::logPrefix() + "Capabilities now: " + capText << std::endl;
+ cap_free(capText);
+
+ cap_free(caps);
+#endif
+ // We assume that on non-Linux we don't need to be root to be able to hardlink to files we
+ // don't own, so drop root.
+ if (geteuid() == 0 && getuid() != 0)
+ {
+ // The program is setuid root. Not normal on Linux where we use setcap, but if this
+ // needs to run on non-Linux Unixes, setuid root is what it will bneed to be to be able
+ // to do chroot().
+ if (setuid(getuid()) != 0)
+ {
+ std::cout << Util::logPrefix() << std::string("setuid() failed: ") + strerror(errno) << std::endl;
+ }
+ }
+#if ENABLE_DEBUG
+ if (geteuid() == 0 && getuid() == 0)
+ {
+#ifdef __linux
+ // Argh, awful hack
+ if (capability == CAP_FOWNER)
+ return;
+#endif
+
+ // Running under sudo, probably because being debugged? Let's drop super-user rights.
+ LOOLWSD::runningAsRoot = true;
+ if (LOOLWSD::uid == 0)
+ {
+ struct passwd *nobody = getpwnam("nobody");
+ if (nobody)
+ LOOLWSD::uid = nobody->pw_uid;
+ else
+ LOOLWSD::uid = 65534;
+ }
+ if (setuid(LOOLWSD::uid) != 0)
+ {
+ Application::instance().logger().error(std::string("setuid() failed: ") + strerror(errno));
+ }
+ }
+#endif
+ }
+}
+
+class PipeRunnable: public Runnable
+{
+public:
+ PipeRunnable()
+ {
+ _pStart = _pEnd = nullptr;
+ }
+
+ ssize_t getResponseLine(int nPipeReader, std::string& aLine)
+ {
+ ssize_t nBytes = -1;
+ aLine.clear();
+
+ while (true)
+ {
+ if ( _pStart == _pEnd )
+ {
+ nBytes = Util::readMessage(nPipeReader, _aBuffer, sizeof(_aBuffer));
+ if ( nBytes < 0 )
+ {
+ _pStart = _pEnd = NULL;
+ break;
+ }
+
+ _pStart = _aBuffer;
+ _pEnd = _aBuffer + nBytes;
+ }
+
+ if ( _pStart != _pEnd )
+ {
+ char aChar = *_pStart++;
+ while (_pStart != _pEnd && aChar != '\r' && aChar != '\n')
+ {
+ aLine += aChar;
+ aChar = *_pStart++;
+ }
+
+ if ( aChar == '\r' && *_pStart == '\n')
+ {
+ _pStart++;
+ break;
+ }
+ }
+ }
+
+ return nBytes;
+ }
+
+ ssize_t sendMessage(int nPipeWriter, const std::string& aMessage)
+ {
+ ssize_t nBytes = -1;
+
+ nBytes = Util::writeFIFO(nPipeWriter, aMessage.c_str(), aMessage.length());
+ if ( nBytes < 0 )
+ std::cout << Util::logPrefix() << "Error writting child: " << strerror(errno) << std::endl;
+
+ return nBytes;
+ }
+
+ ssize_t createThread(Process::PID nPID, const std::string& aTID)
+ {
+ std::string aResponse;
+ std::string aMessage = "thread " + aTID + "\r\n";
+ return sendMessage(_childProcesses[nPID], aMessage);
+ }
+
+ ssize_t updateURL(Process::PID nPID, const std::string& aURL)
+ {
+ std::string aResponse;
+ std::string aMessage = "url " + aURL + "\r\n";
+ return sendMessage(_childProcesses[nPID], aMessage);
+ }
+
+ Process::PID searchURL(const std::string& aURL)
+ {
+ ssize_t nBytes = -1;
+ Process::PID nPID = 0;
+ std::string aResponse;
+ std::string aMessage = "search " + aURL + "\r\n";
+
+ auto aIterator = _childProcesses.begin();
+ for ( ; aIterator!=_childProcesses.end(); ++aIterator)
+ {
+ if ( !(aIterator->first > 0 && aIterator->second > 0) )
+ {
+ //std::cout << Util::logPrefix() << "error iterator " << aIterator->second << " " << aMessage << std::endl;
+ continue;
+ }
+
+ nBytes = Util::writeFIFO(aIterator->second, aMessage.c_str(), aMessage.length());
+ if ( nBytes < 0 )
+ {
+ std::cout << Util::logPrefix() << "Error writting child: " << aIterator->first << " " << strerror(errno) << std::endl;
+ break;
+ }
+
+ nBytes = getResponseLine(readerChild, aResponse);
+ if ( nBytes < 0 )
+ {
+ std::cout << Util::logPrefix() << "Error reading child: " << aIterator->first << " " << strerror(errno) << std::endl;
+ break;
+ }
+
+ //std::cout << Util::logPrefix() << "response: " << aResponse << std::endl;
+ StringTokenizer tokens(aResponse, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+ if (tokens[1] == "ok")
+ {
+ nPID = aIterator->first;
+ }
+ else if (tokens[1] == "empty")
+ {
+ _emptyURL.push_back(aIterator->first);
+ }
+ }
+
+ if ( aIterator != _childProcesses.end() )
+ {
+ _cacheURL.clear();
+ _emptyURL.clear();
+ }
+
+ return (nBytes > 0 ? nPID : -1);
+ }
+
+ void handleInput(const std::string& aMessage)
+ {
+ Process::PID nPID;
+
+ //std::cout << Util::logPrefix() << "Broker,Input," << aMessage << std::endl;
+ StringTokenizer tokens(aMessage, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+ if (tokens[0] == "request" && tokens.count() == 3)
+ {
+ std::string aTID = tokens[1];
+ std::string aURL = tokens[2];
+
+ // check cache
+ auto aIterURL = _cacheURL.find(aURL);
+ if ( aIterURL != _cacheURL.end() )
+ {
+ std::cout << Util::logPrefix() << "Cache Found: " << aIterURL->first << std::endl;
+ if (createThread(aIterURL->second, aTID) < 0)
+ std::cout << Util::logPrefix() << "Cache: Error creating thread: " << strerror(errno) << std::endl;
+
+ return;
+ }
+
+ // not found in cache, full search.
+ nPID = searchURL(aURL);
+ if ( nPID < 0)
+ return;
+
+ if ( nPID > 0 )
+ {
+ std::cout << Util::logPrefix() << "Search Found: " << nPID << std::endl;
+ if (createThread(nPID, aTID) < 0)
+ std::cout << Util::logPrefix() << "Search: Error creating thread: " << strerror(errno) << std::endl;
+ else
+ _cacheURL[aURL] = nPID;
+
+ return;
+ }
+
+ // not found, new URL session.
+ if ( _emptyURL.size() > 0 )
+ {
+ auto aItem = _emptyURL.front();
+ std::cout << Util::logPrefix() << "Not Found: " << aItem << std::endl;
+ if (updateURL(aItem, aURL) < 0)
+ {
+ std::cout << Util::logPrefix() << "New: Error update URL: " << strerror(errno) << std::endl;
+ return;
+ }
+
+ if (createThread(aItem, aTID) < 0)
+ {
+ std::cout << Util::logPrefix() << "New: Error creating thread: " << strerror(errno) << std::endl;
+ return;
+ }
+ _emptyURL.pop_front();
+ _cacheURL[aURL] = aItem;
+ }
+
+ /*if (_emptyURL.size() == 0 )
+ {
+ std::cout << Util::logPrefix() << "No available childs, fork new one" << std::endl;
+ forkCounter++;
+ }*/
+ }
+ }
+
+ void run() override
+ {
+ std::string aMessage;
+ char aBuffer[1024*2];
+ char* pStart;
+ char* pEnd;
+
+ struct pollfd aPoll;
+ ssize_t nBytes = -1;
+
+ aPoll.fd = readerBroker;
+ aPoll.events = POLLIN;
+ aPoll.revents = 0;
+
+ pStart = aBuffer;
+ pEnd = aBuffer;
+
+#ifdef __linux
+ if (prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("pipe_reader"), 0, 0, 0) != 0)
+ std::cout << Util::logPrefix() << "Cannot set thread name :" << strerror(errno) << std::endl;
+#endif
+
+ while (true)
+ {
+ if ( pStart == pEnd )
+ {
+ (void)poll(&aPoll,1,-1);
+
+ if( (aPoll.revents & POLLIN) != 0 )
+ {
+ nBytes = Util::readFIFO(readerBroker, aBuffer, sizeof(aBuffer));
+ if (nBytes < 0)
+ {
+ pStart = pEnd = NULL;
+ std::cout << Util::logPrefix() << "Error reading message :" << strerror(errno) << std::endl;
+ continue;
+ }
+ pStart = aBuffer;
+ pEnd = aBuffer + nBytes;
+ }
+ }
+
+ if ( pStart != pEnd )
+ {
+ char aChar = *pStart++;
+ while (pStart != pEnd && aChar != '\r' && aChar != '\n')
+ {
+ aMessage += aChar;
+ aChar = *pStart++;
+ }
+
+ if ( aChar == '\r' && *pStart == '\n')
+ {
+ pStart++;
+
+ forkMutex.lock();
+ handleInput(aMessage);
+ aMessage.clear();
+ forkMutex.unlock();
+ }
+ }
+ }
+ }
+
+private:
+ char* _pStart;
+ char* _pEnd;
+ char _aBuffer[1024];
+};
+
+/// Initializes LibreOfficeKit for cross-fork re-use.
+static bool globalPreinit(const std::string &loSubPath)
+{
+ void *handle;
+ LokHookPreInit* preInit;
+
+ std::string fname = "/" + loSubPath + "/program/" LIB_SOFFICEAPP;
+ handle = dlopen(fname.c_str(), RTLD_GLOBAL|RTLD_NOW);
+ if (!handle)
+ {
+ std::cout << Util::logPrefix() << " Failed to load library :" << LIB_SOFFICEAPP << std::endl;
+ return false;
+ }
+
+ preInit = (LokHookPreInit *)dlsym(handle, "lok_preinit");
+ if (!preInit)
+ {
+ std::cout << Util::logPrefix() << " Failed to find lok_preinit hook in library :" << LIB_SOFFICEAPP << std::endl;
+ return false;
+ }
+
+ return preInit(("/" + loSubPath + "/program").c_str(), "file:///user") == 0;
+}
+
+static int createLibreOfficeKit(bool sharePages, std::string loSubPath, Poco::UInt64 childID)
+{
+ Poco::UInt64 child;
+ int nFIFOWriter = -1;
+
+ if (sharePages)
+ {
+ Poco::UInt64 pid;
+
+ std::cout << Util::logPrefix() + "Forking LibreOfficeKit" << std::endl;
+
+ if (!(pid = fork()))
+ { // child
+ run_lok_main(loSubPath, childID, "");
+ _exit(0);
+ }
+ else
+ { // parent
+ child = pid; // (somehow - switch the hash to use real pids or ?) ...
+ }
+ }
+ else
+ {
+ Process::Args args;
+ std::string executable = "loolkit";
+ std::string pipe = BROKER_PREFIX + std::to_string(childCounter++) + BROKER_SUFIX;
+
+ if (mkfifo(pipe.c_str(), 0666) < 0)
+ {
+ std::cout << Util::logPrefix() << "mkfifo :" << strerror(errno) << std::endl;
+ return -1;
+ }
+
+ args.push_back("--losubpath=" + loSubPath);
+ args.push_back("--child=" + std::to_string(childID));
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list