From 4ff538c7e15ef45ed95c407b0cbea400d6e22b77 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sat, 1 May 2021 18:38:18 +0200 Subject: [PATCH] Let group hosts shut down on their own if unused We would never try to shut the group host down if nothing ever tried to connect to it. This could happen when the native host gets killed after initializing the yabridge plugin but before it gets the chance to request the group host process to host a plugin. --- CHANGELOG.md | 4 +++ src/wine-host/bridges/group.cpp | 48 ++++++++++++++++++++------------- src/wine-host/bridges/group.h | 7 +++++ 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b6d8dd7..c668c0d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -81,6 +81,10 @@ Versioning](https://semver.org/spec/v2.0.0.html). plugins. We now explicitly reparent the window to back the root window first before deferring the window closing. This should fix the issue, while still keeping editor closing nice and snappy. +- Allow plugin group host processes to shut down by themselves if it doesn't get + a request to host any plugins. This can happen when the DAW gets killed after + starting the group host process but before the native yabridge plugins + requests the group host process to host a plugin. - Prevented latency introducing plugins VST3 from causing **Ardour** and **Mixbus** to freeze when loading the plugin. This for example prevents _Neural DSP Darkglass_ from freezing when used under those DAWs. diff --git a/src/wine-host/bridges/group.cpp b/src/wine-host/bridges/group.cpp index e0017403..66e08c82 100644 --- a/src/wine-host/bridges/group.cpp +++ b/src/wine-host/bridges/group.cpp @@ -150,31 +150,17 @@ void GroupBridge::handle_plugin_run(size_t plugin_id, HostBridge* bridge) { // Defer actually shutting down the process to allow for fast plugin // scanning by allowing plugins to reuse the same group host process - std::lock_guard lock(shutdown_timer_mutex); - shutdown_timer.expires_after(2s); - shutdown_timer.async_wait([this](const boost::system::error_code& error) { - // A previous timer gets canceled automatically when another plugin - // exits - if (error.failed()) { - return; - } - - std::lock_guard lock(active_plugins_mutex); - if (active_plugins.size() == 0) { - logger.log( - "All plugins have exited, shutting down the group process"); - - // main_context.stop(); - // FIXME: See the comment in `individual-host.cpp` - TerminateProcess(GetCurrentProcess(), 0); - } - }); + maybe_schedule_shutdown(4s); } void GroupBridge::handle_incoming_connections() { accept_requests(); async_handle_events(); + // If we don't get a request to host a plugin within ten seconds, we'll shut + // the process down again. + maybe_schedule_shutdown(10s); + logger.log( "Group host is up and running, now accepting incoming connections"); main_context.run(); @@ -332,6 +318,30 @@ boost::asio::local::stream_protocol::acceptor create_acceptor_if_inactive( } } +void GroupBridge::maybe_schedule_shutdown( + std::chrono::steady_clock::duration delay) { + std::lock_guard lock(shutdown_timer_mutex); + + shutdown_timer.expires_after(delay); + shutdown_timer.async_wait([this](const boost::system::error_code& error) { + // A previous timer gets canceled automatically when another plugin + // exits + if (error.failed()) { + return; + } + + std::lock_guard lock(active_plugins_mutex); + if (active_plugins.size() == 0) { + logger.log( + "All plugins have exited, shutting down the group process"); + + // main_context.stop(); + // FIXME: See the comment in `individual-host.cpp` + TerminateProcess(GetCurrentProcess(), 0); + } + }); +} + std::string create_logger_prefix(const fs::path& socket_path) { // The group socket filename will be in the format // '/tmp/yabridge-group---.sock', diff --git a/src/wine-host/bridges/group.h b/src/wine-host/bridges/group.h index 76385af7..fd5ff5b9 100644 --- a/src/wine-host/bridges/group.h +++ b/src/wine-host/bridges/group.h @@ -187,6 +187,13 @@ class GroupBridge { */ void async_handle_events(); + /** + * After `delay` seconds, check if this group host process is (still) + * hosting any plugins. If not, then we'll terminate the process. When this + * function gets called multiple times later calls will reset the timer. + */ + void maybe_schedule_shutdown(std::chrono::steady_clock::duration delay); + /** * The logging facility used for this group host process. Since we can't * identify which plugin is generating (debug) output, every line will only