From 883d389bc283ac6b29b303a94f063e5575f8416f Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Thu, 21 Apr 2022 22:00:03 +0200 Subject: [PATCH] Make hyprctl thread safe --- src/debug/HyprCtl.cpp | 68 +++++++++++++++++++++++++++++++++-------- src/debug/HyprCtl.hpp | 5 +++ src/events/Monitors.cpp | 3 ++ 3 files changed, 63 insertions(+), 13 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 2c45c663..160eaff6 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -111,6 +111,60 @@ std::string dispatchKeyword(std::string in) { return retval; } +void HyprCtl::tickHyprCtl() { + if (!requestMade) + return; + + std::string reply = ""; + + try { + if (request == "monitors") + reply = monitorsRequest(); + else if (request == "workspaces") + reply = workspacesRequest(); + else if (request == "clients") + reply = clientsRequest(); + else if (request == "activewindow") + reply = activeWindowRequest(); + else if (request == "layers") + reply = layersRequest(); + else if (request.find("dispatch") == 0) + reply = dispatchRequest(request); + else if (request.find("keyword") == 0) + reply = dispatchKeyword(request); + } catch (std::exception& e) { + Debug::log(ERR, "Error in request: %s", e.what()); + reply = "Err: " + std::string(e.what()); + } + + request = reply; + + requestMade = false; + requestReady = true; +} + +std::string getRequestFromThread(std::string rq) { + while (HyprCtl::request != "" || HyprCtl::requestMade || HyprCtl::requestReady) { + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + } + + HyprCtl::request = rq; + HyprCtl::requestMade = true; + + while (!HyprCtl::requestReady) { + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + } + + HyprCtl::requestReady = false; + HyprCtl::requestMade = false; + + std::string toReturn = HyprCtl::request; + + HyprCtl::request = ""; + + return toReturn; +} + void HyprCtl::startHyprCtlSocket() { std::thread([&]() { uint16_t connectPort = 9187; @@ -164,19 +218,7 @@ void HyprCtl::startHyprCtlSocket() { std::string request(readBuffer); - std::string reply = ""; - try { - if (request == "monitors") reply = monitorsRequest(); - else if (request == "workspaces") reply = workspacesRequest(); - else if (request == "clients") reply = clientsRequest(); - else if (request == "activewindow") reply = activeWindowRequest(); - else if (request == "layers") reply = layersRequest(); - else if (request.find("dispatch") == 0) reply = dispatchRequest(request); - else if (request.find("keyword") == 0) reply = dispatchKeyword(request); - } catch (std::exception& e) { - Debug::log(ERR, "Error in request: %s", e.what()); - reply = "Err: " + std::string(e.what()); - } + std::string reply = getRequestFromThread(request); write(ACCEPTEDCONNECTION, reply.c_str(), reply.length()); diff --git a/src/debug/HyprCtl.hpp b/src/debug/HyprCtl.hpp index 1efe468f..3da4aa07 100644 --- a/src/debug/HyprCtl.hpp +++ b/src/debug/HyprCtl.hpp @@ -8,5 +8,10 @@ namespace HyprCtl { void startHyprCtlSocket(); void tickHyprCtl(); + // very simple thread-safe request method + inline bool requestMade = false; + inline bool requestReady = false; + inline std::string request = ""; + inline std::ifstream requestStream; }; \ No newline at end of file diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 840602bd..3f1d38e1 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -3,6 +3,7 @@ #include "../managers/InputManager.hpp" #include "../render/Renderer.hpp" #include "Events.hpp" +#include "../debug/HyprCtl.hpp" // --------------------------------------------------------- // // __ __ ____ _ _ _____ _______ ____ _____ _____ // @@ -133,6 +134,8 @@ void Events::listener_monitorFrame(void* owner, void* data) { g_pAnimationManager->tick(); g_pCompositor->cleanupWindows(); + HyprCtl::tickHyprCtl(); // so that we dont get that race condition multithread bullshit + g_pConfigManager->dispatchExecOnce(); // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd if (g_pConfigManager->m_bWantsMonitorReload)