From df65cab17a2257cd12ab70b33a3f7d210bc00b71 Mon Sep 17 00:00:00 2001 From: cptpcrd <31829097+cptpcrd@users.noreply.github.com> Date: Sun, 21 May 2023 12:10:44 -0400 Subject: [PATCH] Open command pipes as close-on-exec Avoids a race where the pipe could be inherited by another process spawning at about the same time. If the other process didn't exit quickly (e.g. if it was a custom script that did its own looping), it would keep the write end of the pipe open, and so reading from the pipe to try to get the command's output would block. This bug manifested as some custom modules randomly not appearing in the bar, requiring a reload to fix. The custom script had run and exited, but the pipe had been inherited by another process, and the thread that updated the module's output was blocked trying to read from it. --- include/util/command.hpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/util/command.hpp b/include/util/command.hpp index c9f238c1..eff9581f 100644 --- a/include/util/command.hpp +++ b/include/util/command.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #ifdef __linux__ #include @@ -68,7 +69,11 @@ inline int close(FILE* fp, pid_t pid) { inline FILE* open(const std::string& cmd, int& pid) { if (cmd == "") return nullptr; int fd[2]; - if (pipe(fd) != 0) { + // Open the pipe with the close-on-exec flag set, so it will not be inherited + // by any other subprocesses launched by other threads (which could result in + // the pipe staying open after this child dies, causing us to hang when trying + // to read from it) + if (pipe2(fd, O_CLOEXEC) != 0) { spdlog::error("Unable to pipe fd"); return nullptr; }