Preventing orphaned processes from rising from the grave and haunting our window manager.

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.

:)
This commit is contained in:
anomaloushuman 2025-03-11 02:54:54 -05:00
parent 5a29688ca2
commit 43da6b51ab
2 changed files with 93 additions and 1 deletions

View file

@ -1,6 +1,12 @@
#include "windowManager.hpp"
#include "./events/events.hpp"
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <map> // Include for mapping window IDs to PIDs
#include <fstream>
#include <mutex>
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<int64_t> dirtyWindows; // Add this to track suspect windows
void CWindowManager::cleanupTerminatedWindows() {
std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> 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
}

View file

@ -7,6 +7,11 @@
#include <thread>
#include <xcb/xcb.h>
#include <deque>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <map>
#include <mutex>
#include "KeybindManager.hpp"
#include "utilities/Workspace.hpp"
@ -154,6 +159,18 @@ public:
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<int64_t, pid_t> windowIDToPIDMap;
std::mutex pidMapMutex;
bool isExpectedProcess(pid_t pid, const std::string& expectedCmdline);
private:
// Internal WM functions that don't have to be exposed