configure.ac | 4 - vcl/unx/gtk3_kde5/gtk3_kde5_filepicker.cxx | 9 -- vcl/unx/gtk3_kde5/gtk3_kde5_filepicker.hxx | 3 vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.cxx | 98 +++++++++++++++++++------ vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.hxx | 29 +++++-- vcl/unx/gtk3_kde5/gtk3_kde5_gtkinst.cxx | 6 - 6 files changed, 101 insertions(+), 48 deletions(-)
New commits: commit cbf0c689d41ba11f37e557c10db7976f8318d43c Author: Milian Wolff <milian.wo...@kdab.com> Date: Wed Jan 24 11:43:20 2018 +0100 Undo "check for boost/process/child.hpp in configure.ac if --enable-gtk3-kde5" This reverts commit c7a1320593191e8359aa64d8e262948da085d358. It's no longer required since we ported away from boost.:process Change-Id: I53c5b994c3ba2801823ba0d6ab25f43223db1476 Reviewed-on: https://gerrit.libreoffice.org/48491 Tested-by: Jenkins <c...@libreoffice.org> Reviewed-by: Thorsten Behrens <thorsten.behr...@cib.de> diff --git a/configure.ac b/configure.ac index 3de79ab4d192..2780d20f7b9b 100644 --- a/configure.ac +++ b/configure.ac @@ -8716,10 +8716,6 @@ if test "$with_system_boost" = "yes"; then [AC_MSG_ERROR(boost/shared_ptr.hpp not found. install boost)], []) AC_CHECK_HEADER(boost/spirit/include/classic_core.hpp, [], [AC_MSG_ERROR(boost/spirit/include/classic_core.hpp not found. install boost >= 1.36)], []) -if test "x$enable_gtk3_kde5" = "xyes"; then - AC_CHECK_HEADER(boost/process/child.hpp, [], - [AC_MSG_ERROR(boost/process/child.hpp not found. install boost >= 1.64)], []) -fi CXXFLAGS=$save_CXXFLAGS AC_LANG_POP([C++]) # this is in m4/ax_boost_base.m4 commit 068f244222edcc5916fe864a0265ab6ccb4e43d2 Author: Milian Wolff <milian.wo...@kdab.com> Date: Wed Jan 24 11:35:20 2018 +0100 gtk3_kde5: port away from boost::process While this uglifies the code, it removes a dependency on newer boost 1.64+ which ships boost::process. This helps on systems where LO is linked against system boost and an older version of boost is used. Additionally, and this is the main motivation, this makes it easier to backport these changes to 5.2, where the bundled boost is also only at 1.60. To keep the required changes at a minimum, the osl_* API for reading from/writing to the stdout/stdin of the helper process, we buffer the responses on a line-by-line basis. Note that one cannot simply reuse osl_readLine on the non-seekable oslFileHandle. Instead, we have to roll our own simplistic readLine implementation... Change-Id: I1197e38cb2416e926d8ba985accd6c10d78bcc52 Reviewed-on: https://gerrit.libreoffice.org/48490 Tested-by: Jenkins <c...@libreoffice.org> Reviewed-by: Thorsten Behrens <thorsten.behr...@cib.de> diff --git a/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker.cxx b/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker.cxx index 7372d476f55e..8c983996b791 100644 --- a/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker.cxx +++ b/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker.cxx @@ -42,13 +42,6 @@ #include <strings.hrc> -#include <future> - -#include <boost/filesystem/path.hpp> -#include <boost/process/environment.hpp> -#include <boost/process/search_path.hpp> -#include <boost/process/io.hpp> - using namespace ::com::sun::star; using namespace ::com::sun::star::ui::dialogs; using namespace ::com::sun::star::ui::dialogs::TemplateDescription; @@ -57,8 +50,6 @@ using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::uno; -namespace bp = boost::process; -namespace bf = boost::filesystem; // helper functions diff --git a/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker.hxx b/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker.hxx index 80261ded9f9b..740382d9ec49 100644 --- a/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker.hxx +++ b/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker.hxx @@ -32,9 +32,6 @@ #include <rtl/ustrbuf.hxx> -#include <boost/process/child.hpp> -#include <boost/process/pipe.hpp> - #include "gtk3_kde5_filepicker_ipc.hxx" #include <functional> diff --git a/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.cxx b/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.cxx index fd9c1c7b64e1..21690c5e74f8 100644 --- a/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.cxx +++ b/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.cxx @@ -26,6 +26,7 @@ #include <strings.hrc> #include <future> +#include <system_error> #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> @@ -41,38 +42,33 @@ #include <unx/gtk/gtkdata.hxx> #include <boost/filesystem/path.hpp> -#include <boost/process/environment.hpp> -#include <boost/process/search_path.hpp> -#include <boost/process/io.hpp> using namespace ::com::sun::star::ui::dialogs; -namespace bp = boost::process; -namespace bf = boost::filesystem; - // helper functions namespace { -bf::path applicationDirPath() +OUString applicationDirPath() { OUString applicationFilePath; osl_getExecutableFile(&applicationFilePath.pData); OUString applicationSystemPath; osl_getSystemPathFromFileURL(applicationFilePath.pData, &applicationSystemPath.pData); - auto sysPath = applicationSystemPath.toUtf8(); - auto ret = bf::path(sysPath.getStr(), sysPath.getStr() + sysPath.getLength()); + const auto utf8Path = applicationSystemPath.toUtf8(); + auto ret = boost::filesystem::path(utf8Path.getStr(), utf8Path.getStr() + utf8Path.getLength()); ret.remove_filename(); - return ret; + return OUString::fromUtf8(OString(ret.c_str(), ret.size())); } -bf::path findPickerExecutable() +OUString findPickerExecutable() { - auto paths = boost::this_process::path(); - paths.insert(paths.begin(), applicationDirPath()); - auto ret = bp::search_path("lo_kde5filepicker", paths); - if (ret.empty()) - throw bp::process_error(std::make_error_code(std::errc::no_such_file_or_directory), + const auto path = applicationDirPath(); + const OUString app("lo_kde5filepicker"); + OUString ret; + osl_searchFileURL(app.pData, path.pData, &ret.pData); + if (ret.isEmpty()) + throw std::system_error(std::make_error_code(std::errc::no_such_file_or_directory), "could not find lo_kde5filepicker executable"); return ret; } @@ -113,16 +109,34 @@ OUString getResString(const char* pResId) // Gtk3KDE5FilePicker Gtk3KDE5FilePickerIpc::Gtk3KDE5FilePickerIpc() - // workaround: specify some non-empty argument, otherwise the Qt app will see argc == 0 - : m_process(findPickerExecutable(), "dummy", bp::std_out > m_stdout, bp::std_in < m_stdin) { + const auto exe = findPickerExecutable(); + oslProcessError result; + oslSecurity pSecurity = osl_getCurrentSecurity(); + result = osl_executeProcess_WithRedirectedIO(exe.pData, nullptr, 0, osl_Process_NORMAL, + pSecurity, nullptr, nullptr, 0, &m_process, + &m_inputWrite, &m_outputRead, nullptr); + osl_freeSecurityHandle(pSecurity); + if (result != osl_Process_E_None) + throw std::system_error(std::make_error_code(std::errc::no_such_process), + "could not start lo_kde5filepicker executable"); } Gtk3KDE5FilePickerIpc::~Gtk3KDE5FilePickerIpc() { + if (!m_process) + return; + sendCommand(Commands::Quit); - if (m_process.running()) - m_process.wait_for(std::chrono::milliseconds(100)); + TimeValue timeValue(std::chrono::milliseconds(100)); + if (osl_joinProcessWithTimeout(m_process, &timeValue) != osl_Process_E_None) + osl_terminateProcess(m_process); + + if (m_inputWrite) + osl_closeFile(m_inputWrite); + if (m_outputRead) + osl_closeFile(m_outputRead); + osl_freeProcessHandle(m_process); } sal_Int16 Gtk3KDE5FilePickerIpc::execute() @@ -198,4 +212,48 @@ void Gtk3KDE5FilePickerIpc::await(const std::future<void>& future) } } +void Gtk3KDE5FilePickerIpc::writeResponseLine(const std::string& line) +{ + sal_uInt64 bytesWritten = 0; + osl_writeFile(m_inputWrite, line.c_str(), line.size(), &bytesWritten); +} + +std::string Gtk3KDE5FilePickerIpc::readResponseLine() +{ + if (!m_responseBuffer.empty()) // check whether we have a line in our buffer + { + auto it = m_responseBuffer.find('\n'); + if (it != std::string::npos) + { + auto ret = m_responseBuffer.substr(0, it); + m_responseBuffer.erase(0, it); + return ret; + } + } + + const sal_uInt64 BUF_SIZE = 1024; + char buffer[BUF_SIZE]; + while (true) + { + sal_uInt64 bytesRead = 0; + auto err = osl_readFile(m_outputRead, buffer, BUF_SIZE, &bytesRead); + auto it = std::find(buffer, buffer + bytesRead, '\n'); + if (it != buffer + bytesRead) // check whether the chunk we read contains an EOL + { + // if so, append that part to the buffer and return it + std::string ret = m_responseBuffer.append(buffer, it); + // but keep anything else we may have read in our buffer + ++it; + m_responseBuffer.assign(it, buffer + bytesRead); + return ret; + } + // otherwise append everything we read to the buffer and try again + m_responseBuffer.append(buffer, bytesRead); + + if (err != osl_File_E_None && err != osl_File_E_AGAIN) + break; + } + return {}; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.hxx b/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.hxx index 8b8bfbc7a726..bed1ae113823 100644 --- a/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.hxx +++ b/vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.hxx @@ -23,32 +23,33 @@ #include <osl/conditn.hxx> #include <osl/mutex.hxx> +#include <osl/process.h> #include <rtl/ustrbuf.hxx> -#include <boost/process/child.hpp> -#include <boost/process/pipe.hpp> - #include "filepicker_ipc_commands.hxx" #include <functional> #include <future> #include <mutex> #include <thread> +#include <sstream> OUString getResString(const char* pResId); class Gtk3KDE5FilePickerIpc { protected: - boost::process::ipstream m_stdout; - boost::process::opstream m_stdin; - boost::process::child m_process; + oslProcess m_process; + oslFileHandle m_inputWrite; + oslFileHandle m_outputRead; // simple multiplexing: every command gets it's own ID that can be used to // read the corresponding response uint64_t m_msgId = 1; std::mutex m_mutex; uint64_t m_incomingResponse = 0; + std::string m_responseBuffer; + std::stringstream m_responseStream; public: explicit Gtk3KDE5FilePickerIpc(); @@ -56,14 +57,20 @@ public: sal_Int16 execute(); + void writeResponseLine(const std::string& line); + template <typename... Args> uint64_t sendCommand(Commands command, const Args&... args) { auto id = m_msgId; ++m_msgId; - sendIpcArgs(m_stdin, id, command, args...); + std::stringstream stream; + sendIpcArgs(stream, id, command, args...); + writeResponseLine(stream.str()); return id; } + std::string readResponseLine(); + template <typename... Args> void readResponse(uint64_t id, Args&... args) { // read synchronously from a background thread and run the eventloop until the value becomes available @@ -76,12 +83,16 @@ public: // check if we need to read (and potentially wait) a response ID if (m_incomingResponse == 0) - readIpcArgs(m_stdout, m_incomingResponse); + { + m_responseStream.clear(); + m_responseStream.str(readResponseLine()); + readIpcArgs(m_responseStream, m_incomingResponse); + } if (m_incomingResponse == id) { // the response we are waiting for came in - readIpcArgs(m_stdout, args...); + readIpcArgs(m_responseStream, args...); m_incomingResponse = 0; break; } diff --git a/vcl/unx/gtk3_kde5/gtk3_kde5_gtkinst.cxx b/vcl/unx/gtk3_kde5/gtk3_kde5_gtkinst.cxx index bed2c049aa3a..d3f797ce9234 100644 --- a/vcl/unx/gtk3_kde5/gtk3_kde5_gtkinst.cxx +++ b/vcl/unx/gtk3_kde5/gtk3_kde5_gtkinst.cxx @@ -22,7 +22,7 @@ #include "gtk3_kde5_filepicker.hxx" #include "gtk3_kde5_folderpicker.hxx" -#include <boost/process/exception.hpp> +#include <system_error> uno::Reference<ui::dialogs::XFilePicker2> GtkInstance::createFilePicker(const uno::Reference<uno::XComponentContext>& xMSF) @@ -31,7 +31,7 @@ GtkInstance::createFilePicker(const uno::Reference<uno::XComponentContext>& xMSF { return uno::Reference<ui::dialogs::XFilePicker2>(new Gtk3KDE5FilePicker(xMSF)); } - catch (const boost::process::process_error& error) + catch (const std::system_error& error) { OSL_FAIL(error.what()); return { nullptr }; @@ -45,7 +45,7 @@ GtkInstance::createFolderPicker(const uno::Reference<uno::XComponentContext>& xM { return uno::Reference<ui::dialogs::XFolderPicker2>(new Gtk3KDE5FolderPicker(xMSF)); } - catch (const boost::process::process_error& error) + catch (const std::system_error& error) { OSL_FAIL(error.what()); return { nullptr }; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits