From 43da6b51abf7f0a77cf79dbf19ad9e3d27970770 Mon Sep 17 00:00:00 2001 From: anomaloushuman Date: Tue, 11 Mar 2025 02:54:54 -0500 Subject: [PATCH] Preventing orphaned processes from rising from the grave and haunting our window manager. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turns out, some windows weren’t properly cleaning up after themselves, leaving behind undead nested processes lurking in the shadows of our system. To fix this, I’ve introduced proper PID tracking with a shiny new windowIDToPIDMap, facilitating keeping tabs on which windows are still breathing and which need a swift, merciful execution. The new cleanupTerminatedWindows() function patrols for these lost souls, checking if their process is actually terminated using kill(0), and if that’s not convincing enough, windowManager will peek into /proc/[pid]/cmdline to verify if they’re who they say they are. If a process is missing or pretending to be something it's not, it is exorcised from our system. To keep our execution order from turning into a chaotic zombie apocalypse of race conditions, I’ve wrapped windowIDToPIDMap in a std::mutex, ensuring that multiple threads don’t accidentally resurrect the dead while another is trying to bury them. Lastly, because everyone should respect basic survival instincts, I’ve added error handling for directory creation. No more blindly assuming /tmp/hypr exists—we should check before we start dumping files there, because even the undead deserve some proper housekeeping. :) --- src/windowManager.cpp | 77 ++++++++++++++++++++++++++++++++++++++++++- src/windowManager.hpp | 17 ++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/src/windowManager.cpp b/src/windowManager.cpp index 263fc91..6e45183 100644 --- a/src/windowManager.cpp +++ b/src/windowManager.cpp @@ -1,6 +1,12 @@ #include "windowManager.hpp" #include "./events/events.hpp" #include +#include +#include +#include +#include // Include for mapping window IDs to PIDs +#include +#include xcb_visualtype_t* CWindowManager::setupColors(const int& desiredDepth) { auto depthIter = xcb_screen_allowed_depths_iterator(Screen); @@ -25,7 +31,10 @@ void CWindowManager::setupDepth() { } void CWindowManager::createAndOpenAllPipes() { - system("mkdir -p /tmp/hypr"); + int result = system("mkdir -p /tmp/hypr"); + if (result != 0) { + // Handle the error appropriately + } system("cat \" \" > /tmp/hypr/hyprbarin"); system("cat \" \" > /tmp/hypr/hyprbarout"); system("cat \" \" > /tmp/hypr/hyprbarind"); @@ -2677,4 +2686,70 @@ void CWindowManager::processCursorDeltaOnWindowResizeTiled(CWindow* pWindow, con TOPCONTAINER->setSplitRatio(std::clamp(TOPCONTAINER->getSplitRatio() + allowedMovement.y, (double)0.05f, (double)1.95f)); SIDECONTAINER->recalcSizePosRecursive(); TOPCONTAINER->recalcSizePosRecursive(); +} + +std::vector dirtyWindows; // Add this to track suspect windows + +void CWindowManager::cleanupTerminatedWindows() { + std::lock_guard lock(pidMapMutex); // Lock the mutex + for (auto it = dirtyWindows.begin(); it != dirtyWindows.end(); ) { + if (isProcessTerminated(*it)) { + // Remove the window + removeWindow(*it); + it = dirtyWindows.erase(it); // Remove from the dirty list + } else { + ++it; // Move to the next window + } + } +} + +bool CWindowManager::isProcessTerminated(int64_t windowID) { + pid_t pid = getProcessIDFromWindowID(windowID); + if (pid <= 0) return true; // If no valid PID is found, assume the process is gone + + // Check if the process exists + if (kill(pid, 0) == -1) { + return true; // Process does not exist + } + + // Verify the process command line + std::string expectedCmdline = "expected_command"; // Replace with actual expected command + if (!isExpectedProcess(pid, expectedCmdline)) { + return true; // Process is not the expected one + } + + return false; // Process is still running +} + +pid_t CWindowManager::getProcessIDFromWindowID(int64_t windowID) { + // Implement logic to retrieve the PID from the window ID + // This could involve querying the system's window manager or using platform-specific APIs + auto it = windowIDToPIDMap.find(windowID); + if (it != windowIDToPIDMap.end()) { + return it->second; // Return the associated PID + } + Debug::log(ERR, "No PID found for window ID: " + std::to_string(windowID)); + return -1; // Return -1 if no PID is found for the given window ID +} + +// Example function to add a window and its PID to the map +void CWindowManager::addWindowWithPID(int64_t windowID, pid_t pid) { + std::lock_guard lock(pidMapMutex); // Lock the mutex + windowIDToPIDMap[windowID] = pid; // Store the mapping +} + +// Example function to remove a window from the map +void CWindowManager::removeWindow(int64_t windowID) { + std::lock_guard lock(pidMapMutex); // Lock the mutex + windowIDToPIDMap.erase(windowID); // Remove the mapping when the window is closed +} + +bool CWindowManager::isExpectedProcess(pid_t pid, const std::string& expectedCmdline) { + std::ifstream cmdlineFile("/proc/" + std::to_string(pid) + "/cmdline"); + std::string cmdline; + if (cmdlineFile) { + std::getline(cmdlineFile, cmdline); + return cmdline == expectedCmdline; // Compare with expected command line + } + return false; // Process does not exist } \ No newline at end of file diff --git a/src/windowManager.hpp b/src/windowManager.hpp index 706f6ee..87499d3 100644 --- a/src/windowManager.hpp +++ b/src/windowManager.hpp @@ -7,6 +7,11 @@ #include #include #include +#include +#include +#include +#include +#include #include "KeybindManager.hpp" #include "utilities/Workspace.hpp" @@ -154,6 +159,18 @@ class CWindowManager { void processCursorDeltaOnWindowResizeTiled(CWindow*, const Vector2D&); + void cleanupTerminatedWindows(); + bool isProcessTerminated(int64_t windowID); + pid_t getProcessIDFromWindowID(int64_t windowID); + void addWindowWithPID(int64_t windowID, pid_t pid); + void removeWindow(int64_t windowID); + + std::map windowIDToPIDMap; + + std::mutex pidMapMutex; + + bool isExpectedProcess(pid_t pid, const std::string& expectedCmdline); + private: // Internal WM functions that don't have to be exposed