mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-07 03:50:11 +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
|
||||
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.
|
||||
*/
|
||||
@@ -75,7 +95,8 @@ GroupBridge::GroupBridge(boost::filesystem::path group_socket_path)
|
||||
stdout_redirect(io_context, STDOUT_FILENO),
|
||||
stderr_redirect(io_context, STDERR_FILENO),
|
||||
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
|
||||
async_log_pipe_lines(stdout_redirect.pipe, stdout_buffer, "[STDOUT] ");
|
||||
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) {
|
||||
// The group socket filename will be in the format
|
||||
// '/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
|
||||
* 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
|
||||
* `create_logger_prefix()` function in `./group.cpp`.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user