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