From 8f2d7488ff69c68398112ded57496fa26081f4d7 Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Tue, 19 Aug 2025 10:00:17 +0200 Subject: [PATCH] Support older systems without O_CLOEXEC Fixes #2645 --- src/jobserver-posix.cc | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/jobserver-posix.cc b/src/jobserver-posix.cc index 0e3c7e250c..af22768f2c 100644 --- src/jobserver-posix.cc +++ src/jobserver-posix.cc @@ -33,6 +33,35 @@ bool IsFifoDescriptor(int fd) { return (ret == 0) && ((info.st_mode & S_IFMT) == S_IFIFO); } +int OpenPipeDescriptor(const char* path, int mode) { +#ifdef O_CLOEXEC + return ::open(path, mode | O_NONBLOCK | O_CLOEXEC); +#else // !defined(O_CLOEXEC) + // O_CLOEXEC is not available on older MacOS versions. + // See https://github.com/ninja-build/ninja/issues/2645 + int fd = ::open(path, mode | O_NONBLOCK); + if (fd < 0) + return fd; + + auto safe_close = [](int fd) { + int saved_errno = errno; + ::close(fd); + errno = saved_errno; + }; + + int flags = fcntl(fd, F_GETFD); + if (flags < 0) { + safe_close(fd); + return -1; + } + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) { + safe_close(fd); + return -1; + } + return fd; +#endif // !defined(O_CLOEXEC) +} + // Implementation of Jobserver::Client for Posix systems class PosixJobserverClient : public Jobserver::Client { public: @@ -83,7 +112,7 @@ class PosixJobserverClient : public Jobserver::Client { *error = "Empty fifo path"; return false; } - read_fd_ = ::open(fifo_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC); + read_fd_ = OpenPipeDescriptor(fifo_path.c_str(), O_RDONLY); if (read_fd_ < 0) { *error = std::string("Error opening fifo for reading: ") + strerror(errno); @@ -94,7 +123,7 @@ class PosixJobserverClient : public Jobserver::Client { // Let destructor close read_fd_. return false; } - write_fd_ = ::open(fifo_path.c_str(), O_WRONLY | O_NONBLOCK | O_CLOEXEC); + write_fd_ = OpenPipeDescriptor(fifo_path.c_str(), O_WRONLY); if (write_fd_ < 0) { *error = std::string("Error opening fifo for writing: ") + strerror(errno);