From 5a29473080cb63b372204d94e70cc9bd28f94fe4 Mon Sep 17 00:00:00 2001 From: Lukas Fleischer Date: Fri, 22 Aug 2025 18:44:20 -0400 Subject: [PATCH] Prevent child zombie process from tearing down Hyprland IPC In rare circumstances, we may fork(), e.g., as part of a custom module, and the child process may fail to exec() and exit. In those cases, the IPC destructor will be called in the child process. Prior to this commit, this call would then result in the shared socket being closed. Prevent this by only closing the socket from the original process. Fixes #3975 and #4152. Signed-off-by: Lukas Fleischer --- include/modules/hyprland/backend.hpp | 1 + src/modules/hyprland/backend.cpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/include/modules/hyprland/backend.hpp b/include/modules/hyprland/backend.hpp index d9f16526..c94c4705 100644 --- a/include/modules/hyprland/backend.hpp +++ b/include/modules/hyprland/backend.hpp @@ -42,6 +42,7 @@ class IPC { util::JsonParser parser_; std::list> callbacks_; int socketfd_; // the hyprland socket file descriptor + pid_t socketOwnerPid_; bool running_ = true; }; diff --git a/src/modules/hyprland/backend.cpp b/src/modules/hyprland/backend.cpp index 2bd3b509..2c7684be 100644 --- a/src/modules/hyprland/backend.cpp +++ b/src/modules/hyprland/backend.cpp @@ -46,9 +46,14 @@ std::filesystem::path IPC::getSocketFolder(const char* instanceSig) { IPC::IPC() { // will start IPC and relay events to parseIPC ipcThread_ = std::thread([this]() { socketListener(); }); + socketOwnerPid_ = getpid(); } IPC::~IPC() { + // Do no stop Hyprland IPC if a child process (with successful fork() but + // failed exec()) exits. + if (getpid() != socketOwnerPid_) return; + running_ = false; spdlog::info("Hyprland IPC stopping..."); if (socketfd_ != -1) {