mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-10 04:30:12 +02:00
Add handling for stale and active group sockets
This commit is contained in:
@@ -27,6 +27,26 @@
|
|||||||
// path operation will thrown an encoding related error
|
// path operation will thrown an encoding related error
|
||||||
namespace fs = boost::filesystem;
|
namespace fs = boost::filesystem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listen on the specified endpoint if no process is already listening there,
|
||||||
|
* otherwise throw. This is needed to handle these three situations:
|
||||||
|
*
|
||||||
|
* 1. The endpoint does not already exist, and we can simply create an endpoint.
|
||||||
|
* 2. The endpoint already exists but it is stale and no process is currently
|
||||||
|
* listening. In this case we can remove the file and start listening.
|
||||||
|
* 3. The endpoint already exists and another process is currently listening on
|
||||||
|
* it. In this situation we will throw immediately and we'll terminate this
|
||||||
|
* process.
|
||||||
|
*
|
||||||
|
* If anyone knows a better way to handle this, please let me know!
|
||||||
|
*
|
||||||
|
* @throw std::runtime_error If another process is already listening on the
|
||||||
|
* endpoint.
|
||||||
|
*/
|
||||||
|
boost::asio::local::stream_protocol::acceptor create_acceptor_if_inactive(
|
||||||
|
boost::asio::io_context& io_context,
|
||||||
|
boost::asio::local::stream_protocol::endpoint& endpoint);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a logger prefix containing the group name based on the socket path.
|
* Create a logger prefix containing the group name based on the socket path.
|
||||||
*/
|
*/
|
||||||
@@ -75,7 +95,8 @@ GroupBridge::GroupBridge(boost::filesystem::path group_socket_path)
|
|||||||
stdout_redirect(io_context, STDOUT_FILENO),
|
stdout_redirect(io_context, STDOUT_FILENO),
|
||||||
stderr_redirect(io_context, STDERR_FILENO),
|
stderr_redirect(io_context, STDERR_FILENO),
|
||||||
group_socket_endpoint(group_socket_path.string()),
|
group_socket_endpoint(group_socket_path.string()),
|
||||||
group_socket_acceptor(io_context, group_socket_endpoint) {
|
group_socket_acceptor(
|
||||||
|
create_acceptor_if_inactive(io_context, group_socket_endpoint)) {
|
||||||
// Write this process's original STDOUT and STDERR streams to the logger
|
// 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(stdout_redirect.pipe, stdout_buffer, "[STDOUT] ");
|
||||||
async_log_pipe_lines(stderr_redirect.pipe, stderr_buffer, "[STDERR] ");
|
async_log_pipe_lines(stderr_redirect.pipe, stderr_buffer, "[STDERR] ");
|
||||||
@@ -179,6 +200,39 @@ void GroupBridge::async_log_pipe_lines(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::asio::local::stream_protocol::acceptor create_acceptor_if_inactive(
|
||||||
|
boost::asio::io_context& io_context,
|
||||||
|
boost::asio::local::stream_protocol::endpoint& endpoint) {
|
||||||
|
// First try to listen on the endpoint normally
|
||||||
|
try {
|
||||||
|
return boost::asio::local::stream_protocol::acceptor(io_context,
|
||||||
|
endpoint);
|
||||||
|
} catch (const boost::system::system_error& error) {
|
||||||
|
// If this failed, then either there is a stale socket file or another
|
||||||
|
// process is already is already listening. In the last case we will
|
||||||
|
// simply throw so the other process can handle the request.
|
||||||
|
std::ifstream open_sockets("/proc/net/unix");
|
||||||
|
std::string endpoint_path = endpoint.path();
|
||||||
|
for (std::string line; std::getline(open_sockets, line);) {
|
||||||
|
if (line.size() < endpoint_path.size()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string file = line.substr(line.size() - endpoint_path.size());
|
||||||
|
if (file == endpoint_path) {
|
||||||
|
// Another process is already listening, so we don't have to do
|
||||||
|
// anything
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point we can remove the stale socket and start listening
|
||||||
|
fs::remove(endpoint_path);
|
||||||
|
return boost::asio::local::stream_protocol::acceptor(io_context,
|
||||||
|
endpoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string create_logger_prefix(const fs::path& socket_path) {
|
std::string create_logger_prefix(const fs::path& socket_path) {
|
||||||
// The group socket filename will be in the format
|
// The group socket filename will be in the format
|
||||||
// '/tmp/yabridge-group-<group_name>-<wine_prefix_id>-<architecture>.sock',
|
// '/tmp/yabridge-group-<group_name>-<wine_prefix_id>-<architecture>.sock',
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ class GroupBridge {
|
|||||||
*
|
*
|
||||||
* @param gruop_socket_path The path to the group socket endpoint. This path
|
* @param gruop_socket_path The path to the group socket endpoint. This path
|
||||||
* should be in the form of
|
* should be in the form of
|
||||||
* `/tmp/yabridge-group-<group_name>-<wine_prefix_id>-<architecture>`
|
* `/tmp/yabridge-group-<group_name>-<wine_prefix_id>-<architecture>.sock`
|
||||||
* where `<wine_prefix_id>` is a numerical hash as explained in the
|
* where `<wine_prefix_id>` is a numerical hash as explained in the
|
||||||
* `create_logger_prefix()` function in `./group.cpp`.
|
* `create_logger_prefix()` function in `./group.cpp`.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user