diff options
author | Milian Wolff <milian.wolff@kdab.com> | 2018-01-24 11:35:20 +0100 |
---|---|---|
committer | Thorsten Behrens <Thorsten.Behrens@CIB.de> | 2018-01-25 12:24:44 +0100 |
commit | 068f244222edcc5916fe864a0265ab6ccb4e43d2 (patch) | |
tree | 4ede6f428fbb38ca50191633d6fd42db2ffd2294 /vcl/unx | |
parent | 390fad39a8f945c848ff998d9f75720318781123 (diff) |
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 <ci@libreoffice.org>
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
Diffstat (limited to 'vcl/unx')
-rw-r--r-- | vcl/unx/gtk3_kde5/gtk3_kde5_filepicker.cxx | 9 | ||||
-rw-r--r-- | vcl/unx/gtk3_kde5/gtk3_kde5_filepicker.hxx | 3 | ||||
-rw-r--r-- | vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.cxx | 98 | ||||
-rw-r--r-- | vcl/unx/gtk3_kde5/gtk3_kde5_filepicker_ipc.hxx | 29 | ||||
-rw-r--r-- | vcl/unx/gtk3_kde5/gtk3_kde5_gtkinst.cxx | 6 |
5 files changed, 101 insertions, 44 deletions
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 }; |