From a9c3630d1bb2760546470845c34fcc1dc04bb561 Mon Sep 17 00:00:00 2001 From: dominicpoeschko <45942148+dominicpoeschko@users.noreply.github.com> Date: Fri, 7 Feb 2020 17:59:11 +0100 Subject: [PATCH] Properly handling SPDLOG_PREVENT_CHILD_FD Using the SPDLOG_PREVENT_CHILD_FD option there where still a race when a other thread was using fork and exec in between the call to fopen and fcntl. Using open and O_CLOEXEC when possible prevents this race. I have no idea if this problem exists on Windows. --- include/spdlog/details/os-inl.h | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/include/spdlog/details/os-inl.h b/include/spdlog/details/os-inl.h index 8473eb09..b306e318 100644 --- a/include/spdlog/details/os-inl.h +++ b/include/spdlog/details/os-inl.h @@ -153,10 +153,26 @@ SPDLOG_INLINE bool fopen_s(FILE **fp, const filename_t &filename, const filename *fp = ::_fsopen((filename.c_str()), mode.c_str(), _SH_DENYNO); #endif #else // unix +#if defined(SPDLOG_PREVENT_CHILD_FD) && (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) + // prevent child processes from inheriting log file descriptors direcly on open + // so there is no race with a possible fork and exec + const int mode_flag = mode == SPDLOG_FILENAME_T("ab") ? O_APPEND : O_TRUNC; + const int fd = ::open((filename.c_str()), O_CREAT | O_WRONLY | O_CLOEXEC | mode_flag, mode_t(0644)); + if(fd == -1) + { + return false; + } + *fp = ::fdopen(fd, mode.c_str()); + if (*fp == nullptr) + { + ::close(fd); + } +#else *fp = ::fopen((filename.c_str()), mode.c_str()); #endif +#endif -#ifdef SPDLOG_PREVENT_CHILD_FD +#if defined(SPDLOG_PREVENT_CHILD_FD) && !(defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) // prevent child processes from inheriting log file descriptors if (*fp != nullptr) {