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.pull/2182/head
parent
7b704071ff
commit
df65cab17a
|
@ -4,6 +4,7 @@
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
@ -68,7 +69,11 @@ inline int close(FILE* fp, pid_t pid) {
|
||||||
inline FILE* open(const std::string& cmd, int& pid) {
|
inline FILE* open(const std::string& cmd, int& pid) {
|
||||||
if (cmd == "") return nullptr;
|
if (cmd == "") return nullptr;
|
||||||
int fd[2];
|
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");
|
spdlog::error("Unable to pipe fd");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue