Retry hypr socket operations.

Don't immediately ASSERT when the hyprland socket operations fail.
Instead, retry them a few times and then return gracefully instead of
crashing.

https://github.com/scorpion-26/gBar/issues/32
This commit is contained in:
scorpion-26 2023-08-08 16:31:05 +02:00
parent 3bac707bf5
commit ef925ef174
2 changed files with 57 additions and 6 deletions

View file

@ -85,6 +85,29 @@ namespace Utils
return buf; return buf;
} }
template<typename Func>
size_t RetrySocketOp(Func func, size_t retries, const char* socketOp)
{
ssize_t ret;
size_t tries = 0;
do
{
ret = func();
if (ret < 0)
{
// Error
LOG("RetrySocketOp: " << socketOp << " failed with " << ret);
}
else
{
return ret;
}
tries++;
} while (tries < retries);
LOG("RetrySocketOp: Failed after " << retries << "tries");
return ret;
}
inline std::vector<std::string> Split(const std::string& str, char delim) inline std::vector<std::string> Split(const std::string& str, char delim)
{ {
std::stringstream strstr(str); std::stringstream strstr(str);

View file

@ -90,21 +90,49 @@ namespace Workspaces
addr.sun_family = AF_UNIX; addr.sun_family = AF_UNIX;
memcpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path)); memcpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path));
int ret = connect(hyprSocket, (sockaddr*)&addr, SUN_LEN(&addr)); int ret = Utils::RetrySocketOp(
ASSERT(ret >= 0, "Couldn't connect to hyprland socket"); [&]()
ssize_t written = write(hyprSocket, arg.c_str(), arg.size()); {
ASSERT(written >= 0, "Couldn't write to socket"); return connect(hyprSocket, (sockaddr*)&addr, SUN_LEN(&addr));
},
5, "connect");
if (ret < 0)
{
LOG("Couldn't connect to Hyprland socket.");
return "";
}
ssize_t written = Utils::RetrySocketOp(
[&]()
{
return write(hyprSocket, arg.c_str(), arg.size());
},
5, "write");
if (written < 0)
{
LOG("Couldn't write to Hyprland socket.");
return "";
}
char buf[2056]; char buf[2056];
std::string res; std::string res;
while (true) while (true)
{ {
ssize_t bytesRead = read(hyprSocket, buf, sizeof(buf)); ssize_t bytesRead = Utils::RetrySocketOp(
[&]()
{
return read(hyprSocket, buf, sizeof(buf));
},
5, "read");
if (bytesRead == 0) if (bytesRead == 0)
{ {
break; break;
} }
ASSERT(bytesRead >= 0, "Couldn't read"); if (bytesRead < 0)
{
LOG("Couldn't read from Hyprland socket.");
return "";
}
res += std::string(buf, bytesRead); res += std::string(buf, bytesRead);
} }
close(hyprSocket); close(hyprSocket);