mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-09 20:29:10 +02:00
Work around a regression in Wine 6.5
Killing a Wine process no longer terminates its threads, see the changelog entry and NOTE for more information.
This commit is contained in:
+8
-1
@@ -8,7 +8,14 @@ Versioning](https://semver.org/spec/v2.0.0.html).
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
### Yabridgectl
|
### Fixed
|
||||||
|
|
||||||
|
- Work around a regression in Wine 6.5 that would prevent yabridge from shutting
|
||||||
|
down. With Wine 6.5 terminating a Wine process no longer terminates its
|
||||||
|
threads, which would cause yabridge's plugin and host components to wait for
|
||||||
|
each other to shut down.
|
||||||
|
|
||||||
|
### yabridgectl
|
||||||
|
|
||||||
- Minor spelling fixes.
|
- Minor spelling fixes.
|
||||||
|
|
||||||
|
|||||||
@@ -84,11 +84,12 @@ class PluginBridge {
|
|||||||
io_context,
|
io_context,
|
||||||
generic_logger,
|
generic_logger,
|
||||||
info,
|
info,
|
||||||
HostRequest{.plugin_type = plugin_type,
|
HostRequest{
|
||||||
.plugin_path =
|
.plugin_type = plugin_type,
|
||||||
info.windows_plugin_path.string(),
|
.plugin_path =
|
||||||
.endpoint_base_dir =
|
info.windows_plugin_path.string(),
|
||||||
sockets.base_dir.string()}))),
|
.endpoint_base_dir = sockets.base_dir.string()},
|
||||||
|
sockets))),
|
||||||
has_realtime_priority(has_realtime_priority_promise.get_future()),
|
has_realtime_priority(has_realtime_priority_promise.get_future()),
|
||||||
wine_io_handler([&]() {
|
wine_io_handler([&]() {
|
||||||
// We no longer run this thread with realtime scheduling because
|
// We no longer run this thread with realtime scheduling because
|
||||||
|
|||||||
@@ -56,8 +56,13 @@ bp::child launch_host(fs::path host_path, Args&&... args) {
|
|||||||
bp::posix::use_vfork, std::forward<Args>(args)...);
|
bp::posix::use_vfork, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
HostProcess::HostProcess(boost::asio::io_context& io_context, Logger& logger)
|
HostProcess::HostProcess(boost::asio::io_context& io_context,
|
||||||
: stdout_pipe(io_context), stderr_pipe(io_context), logger(logger) {
|
Logger& logger,
|
||||||
|
Sockets& sockets)
|
||||||
|
: stdout_pipe(io_context),
|
||||||
|
stderr_pipe(io_context),
|
||||||
|
sockets(sockets),
|
||||||
|
logger(logger) {
|
||||||
// Print the Wine host's STDOUT and STDERR streams to the log file. This
|
// Print the Wine host's STDOUT and STDERR streams to the log file. This
|
||||||
// should be done before trying to accept the sockets as otherwise we will
|
// should be done before trying to accept the sockets as otherwise we will
|
||||||
// miss all output.
|
// miss all output.
|
||||||
@@ -68,8 +73,9 @@ HostProcess::HostProcess(boost::asio::io_context& io_context, Logger& logger)
|
|||||||
IndividualHost::IndividualHost(boost::asio::io_context& io_context,
|
IndividualHost::IndividualHost(boost::asio::io_context& io_context,
|
||||||
Logger& logger,
|
Logger& logger,
|
||||||
const PluginInfo& plugin_info,
|
const PluginInfo& plugin_info,
|
||||||
const HostRequest& host_request)
|
const HostRequest& host_request,
|
||||||
: HostProcess(io_context, logger),
|
Sockets& sockets)
|
||||||
|
: HostProcess(io_context, logger, sockets),
|
||||||
plugin_info(plugin_info),
|
plugin_info(plugin_info),
|
||||||
host_path(find_vst_host(plugin_info.native_library_path,
|
host_path(find_vst_host(plugin_info.native_library_path,
|
||||||
plugin_info.plugin_arch,
|
plugin_info.plugin_arch,
|
||||||
@@ -109,6 +115,13 @@ bool IndividualHost::running() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IndividualHost::terminate() {
|
void IndividualHost::terminate() {
|
||||||
|
// NOTE: This technically shouldn't be needed, but in Wine 6.5 sending
|
||||||
|
// SIGKILL to a Wine process no longer terminates the threads spawned
|
||||||
|
// by that process, so if we don't manually close the sockets there
|
||||||
|
// will still be threads listening on those sockets which in turn also
|
||||||
|
// prevents us from joining our `std::jthread`s on the plugin side.
|
||||||
|
sockets.close();
|
||||||
|
|
||||||
host.terminate();
|
host.terminate();
|
||||||
// NOTE: This leaves a zombie, because Boost.Process will actually not call
|
// NOTE: This leaves a zombie, because Boost.Process will actually not call
|
||||||
// `wait()` after we have terminated the process.
|
// `wait()` after we have terminated the process.
|
||||||
@@ -121,12 +134,11 @@ GroupHost::GroupHost(boost::asio::io_context& io_context,
|
|||||||
const HostRequest& host_request,
|
const HostRequest& host_request,
|
||||||
Sockets& sockets,
|
Sockets& sockets,
|
||||||
std::string group_name)
|
std::string group_name)
|
||||||
: HostProcess(io_context, logger),
|
: HostProcess(io_context, logger, sockets),
|
||||||
plugin_info(plugin_info),
|
plugin_info(plugin_info),
|
||||||
host_path(find_vst_host(plugin_info.native_library_path,
|
host_path(find_vst_host(plugin_info.native_library_path,
|
||||||
plugin_info.plugin_arch,
|
plugin_info.plugin_arch,
|
||||||
true)),
|
true)) {
|
||||||
sockets(sockets) {
|
|
||||||
#ifdef WITH_WINEDBG
|
#ifdef WITH_WINEDBG
|
||||||
if (plugin_info.windows_plugin_path.string().find(' ') !=
|
if (plugin_info.windows_plugin_path.string().find(' ') !=
|
||||||
std::string::npos) {
|
std::string::npos) {
|
||||||
|
|||||||
+20
-11
@@ -68,8 +68,13 @@ class HostProcess {
|
|||||||
* handled on.
|
* handled on.
|
||||||
* @param logger The `Logger` instance the redirected STDIO streams will be
|
* @param logger The `Logger` instance the redirected STDIO streams will be
|
||||||
* written to.
|
* written to.
|
||||||
|
* @param sockets The socket endpoints that will be used for communication
|
||||||
|
* with the plugin. When the plugin shuts down, we'll close all of the
|
||||||
|
* sockets used by the plugin.
|
||||||
*/
|
*/
|
||||||
HostProcess(boost::asio::io_context& io_context, Logger& logger);
|
HostProcess(boost::asio::io_context& io_context,
|
||||||
|
Logger& logger,
|
||||||
|
Sockets& sockets);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The STDOUT stream of the Wine process we can forward to the logger.
|
* The STDOUT stream of the Wine process we can forward to the logger.
|
||||||
@@ -80,6 +85,12 @@ class HostProcess {
|
|||||||
*/
|
*/
|
||||||
patched_async_pipe stderr_pipe;
|
patched_async_pipe stderr_pipe;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The associated sockets for the plugin we're hosting. This is used to
|
||||||
|
* terminate the plugin.
|
||||||
|
*/
|
||||||
|
Sockets& sockets;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* The logger the Wine output will be written to.
|
* The logger the Wine output will be written to.
|
||||||
@@ -108,6 +119,9 @@ class IndividualHost : public HostProcess {
|
|||||||
* @param host_request The information about the plugin we should launch a
|
* @param host_request The information about the plugin we should launch a
|
||||||
* host process for. The values in the struct will be used as command line
|
* host process for. The values in the struct will be used as command line
|
||||||
* arguments.
|
* arguments.
|
||||||
|
* @param sockets The socket endpoints that will be used for communication
|
||||||
|
* with the plugin. When the plugin shuts down, we'll close all of the
|
||||||
|
* sockets used by the plugin.
|
||||||
*
|
*
|
||||||
* @throw std::runtime_error When `plugin_path` does not point to a valid
|
* @throw std::runtime_error When `plugin_path` does not point to a valid
|
||||||
* 32-bit or 64-bit .dll file.
|
* 32-bit or 64-bit .dll file.
|
||||||
@@ -115,7 +129,8 @@ class IndividualHost : public HostProcess {
|
|||||||
IndividualHost(boost::asio::io_context& io_context,
|
IndividualHost(boost::asio::io_context& io_context,
|
||||||
Logger& logger,
|
Logger& logger,
|
||||||
const PluginInfo& plugin_info,
|
const PluginInfo& plugin_info,
|
||||||
const HostRequest& host_request);
|
const HostRequest& host_request,
|
||||||
|
Sockets& sockets);
|
||||||
|
|
||||||
boost::filesystem::path path() override;
|
boost::filesystem::path path() override;
|
||||||
bool running() override;
|
bool running() override;
|
||||||
@@ -153,15 +168,15 @@ class GroupHost : public HostProcess {
|
|||||||
* @param host_request The information about the plugin we should launch a
|
* @param host_request The information about the plugin we should launch a
|
||||||
* host process for. This object will be sent to the group host process.
|
* host process for. This object will be sent to the group host process.
|
||||||
* @param sockets The socket endpoints that will be used for communication
|
* @param sockets The socket endpoints that will be used for communication
|
||||||
* with the plugin. When the plugin shuts down, we'll terminate the
|
* with the plugin. When the plugin shuts down, we'll close all of the
|
||||||
* dispatch socket contained in this object.
|
* sockets used by the plugin.
|
||||||
* @param group_name The name of the plugin group.
|
* @param group_name The name of the plugin group.
|
||||||
*/
|
*/
|
||||||
GroupHost(boost::asio::io_context& io_context,
|
GroupHost(boost::asio::io_context& io_context,
|
||||||
Logger& logger,
|
Logger& logger,
|
||||||
const PluginInfo& plugin_info,
|
const PluginInfo& plugin_info,
|
||||||
const HostRequest& host_request,
|
const HostRequest& host_request,
|
||||||
Sockets& socket_endpoint,
|
Sockets& sockets,
|
||||||
std::string group_name);
|
std::string group_name);
|
||||||
|
|
||||||
boost::filesystem::path path() override;
|
boost::filesystem::path path() override;
|
||||||
@@ -190,12 +205,6 @@ class GroupHost : public HostProcess {
|
|||||||
*/
|
*/
|
||||||
std::atomic_bool startup_failed;
|
std::atomic_bool startup_failed;
|
||||||
|
|
||||||
/**
|
|
||||||
* The associated sockets for the plugin we're hosting. This is used to
|
|
||||||
* terminate the plugin.
|
|
||||||
*/
|
|
||||||
Sockets& sockets;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A thread that waits for the group host to have started and then ask it to
|
* A thread that waits for the group host to have started and then ask it to
|
||||||
* host our plugin. This is used to defer the request since it may take a
|
* host our plugin. This is used to defer the request since it may take a
|
||||||
|
|||||||
Reference in New Issue
Block a user