From bbfe522343388a322ec7a5577d6bb3e5765be18a Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Mon, 25 May 2020 15:15:32 +0200 Subject: [PATCH] Use a seperate thread for STDIO capture for groups When running the plugins on the main thread the window message loop may block for a while, which would cause the STDIO redirect to be interrupted. --- src/wine-host/bridges/group.cpp | 12 ++++++++++-- src/wine-host/bridges/group.h | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/wine-host/bridges/group.cpp b/src/wine-host/bridges/group.cpp index b7236099..4368b4b9 100644 --- a/src/wine-host/bridges/group.cpp +++ b/src/wine-host/bridges/group.cpp @@ -92,8 +92,9 @@ GroupBridge::GroupBridge(boost::filesystem::path group_socket_path) : logger(Logger::create_from_environment( create_logger_prefix(group_socket_path))), io_context(), - stdout_redirect(io_context, STDOUT_FILENO), - stderr_redirect(io_context, STDERR_FILENO), + stdio_context(), + stdout_redirect(stdio_context, STDOUT_FILENO), + stderr_redirect(stdio_context, STDERR_FILENO), group_socket_endpoint(group_socket_path.string()), group_socket_acceptor( create_acceptor_if_inactive(io_context, group_socket_endpoint)), @@ -101,6 +102,13 @@ GroupBridge::GroupBridge(boost::filesystem::path group_socket_path) // Write this process's original STDOUT and STDERR streams to the logger async_log_pipe_lines(stdout_redirect.pipe, stdout_buffer, "[STDOUT] "); async_log_pipe_lines(stderr_redirect.pipe, stderr_buffer, "[STDERR] "); + + stdio_handler = std::thread([&]() { stdio_context.run(); }); +} + +GroupBridge::~GroupBridge() { + stdio_context.stop(); + stdio_handler.join(); } void GroupBridge::handle_host_plugin(const GroupRequest request) { diff --git a/src/wine-host/bridges/group.h b/src/wine-host/bridges/group.h index fa2909f2..aaa395e3 100644 --- a/src/wine-host/bridges/group.h +++ b/src/wine-host/bridges/group.h @@ -22,6 +22,8 @@ #include #include +#include + #include "vst2.h" /** @@ -116,6 +118,11 @@ class GroupBridge { */ GroupBridge(boost::filesystem::path group_socket_path); + ~GroupBridge(); + + GroupBridge(const GroupBridge&) = delete; + GroupBridge& operator=(const GroupBridge&) = delete; + /** * Host a new plugin within this process. Called by proxy using * `handle_host_plugin_proxy()` in `./group.cpp` because the Win32 @@ -180,6 +187,14 @@ class GroupBridge { Logger logger; boost::asio::io_context io_context; + /** + * A seperate IO context that handles the STDIO redirect through + * `StdIoCapture`. This is seperated the `plugin_context` above so that + * STDIO capture does not get blocked by blocking GUI operations. Since + * every GUI related operation should be run from the same thread, we can't + * just add another thread to the main IO context. + */ + boost::asio::io_context stdio_context; boost::asio::streambuf stdout_buffer; boost::asio::streambuf stderr_buffer; @@ -195,6 +210,10 @@ class GroupBridge { * able write it write it to an external log file. */ StdIoCapture stderr_redirect; + /** + * A thread that runs the `stdio_context` loop. + */ + std::thread stdio_handler; boost::asio::local::stream_protocol::endpoint group_socket_endpoint; /**