From e2fec6eb56c40c49f632c28ee539705bdd799dd2 Mon Sep 17 00:00:00 2001 From: Joseph Prince <57415450+josephdprince@users.noreply.github.com> Date: Tue, 10 Feb 2026 07:27:58 -0800 Subject: [PATCH] SERVER-117564 Properly handle null device for logpath on Windows (#47618) GitOrigin-RevId: 035f5404e0ef01c1b454c3b204a7d254e1ef1568 --- src/mongo/db/initialize_server_global_state.cpp | 9 ++++++--- src/mongo/logv2/file_rotate_sink.cpp | 15 ++++++++++++++- src/mongo/logv2/log_util.h | 15 +++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/mongo/db/initialize_server_global_state.cpp b/src/mongo/db/initialize_server_global_state.cpp index 6e12dc6d219..20329032b54 100644 --- a/src/mongo/db/initialize_server_global_state.cpp +++ b/src/mongo/db/initialize_server_global_state.cpp @@ -78,6 +78,10 @@ #include #include +#ifdef _WIN32 +#include "mongo/logv2/log_util.h" +#endif + #if defined(MONGO_CONFIG_HAVE_HEADER_UNISTD_H) #include #endif @@ -376,9 +380,8 @@ MONGO_INITIALIZER_GENERAL(ServerLogRedirection, fassert(16448, !serverGlobalParams.logWithSyslog); auto [absoluteLogpath, exists] = [&] { #ifdef _WIN32 - constexpr auto kWindowsNUL = "NUL"_sd; - if (serverGlobalParams.logpath == kWindowsNUL) { - return std::make_tuple(std::string(kWindowsNUL), true); + if (logv2::isLogPathWindowsNul(serverGlobalParams.logpath)) { + return std::make_tuple(std::string(logv2::kWindowsNUL), true); } #endif // defined(_WIN32) std::string absolutePath = diff --git a/src/mongo/logv2/file_rotate_sink.cpp b/src/mongo/logv2/file_rotate_sink.cpp index bc6dddaed90..fe9888808cd 100644 --- a/src/mongo/logv2/file_rotate_sink.cpp +++ b/src/mongo/logv2/file_rotate_sink.cpp @@ -69,6 +69,10 @@ #include "mongo/util/string_map.h" #include "mongo/util/time_support.h" +#ifdef _WIN32 +#include "mongo/logv2/log_util.h" +#endif + namespace mongo::logv2 { namespace { @@ -78,12 +82,21 @@ using stream_t = Win32SharedAccessOfstream; using stream_t = std::ofstream; #endif +bool checkLogFileExists(const std::string& filename) { +#ifdef _WIN32 + if (isLogPathWindowsNul(filename)) { + return true; + } +#endif + return boost::filesystem::exists(filename); +} + StatusWith> openFile(const std::string& filename, bool append) { std::ios_base::openmode mode = std::ios_base::out; bool exists = false; if (append) { mode |= std::ios_base::app; - exists = boost::filesystem::exists(filename); + exists = checkLogFileExists(filename); } else mode |= std::ios_base::trunc; auto file = boost::make_shared(filename, mode); diff --git a/src/mongo/logv2/log_util.h b/src/mongo/logv2/log_util.h index f6d76aabfe1..c01b09bfff5 100644 --- a/src/mongo/logv2/log_util.h +++ b/src/mongo/logv2/log_util.h @@ -31,6 +31,7 @@ #include "mongo/base/status.h" #include "mongo/base/string_data.h" +#include "mongo/util/str.h" #include @@ -42,6 +43,10 @@ namespace mongo::logv2 { constexpr auto kServerLogTag = "server"_sd; constexpr auto kAuditLogTag = "audit"_sd; +#ifdef _WIN32 +constexpr auto kWindowsNUL = "nul"_sd; +#endif + using LogRotateCallback = std::function)>; using ShouldEmitLogServiceFn = std::function; @@ -116,4 +121,14 @@ bool shouldEmitLogService(); */ void setShouldEmitLogService(ShouldEmitLogServiceFn fn); +#ifdef _WIN32 +/** + * Checks for the Windows NUL file. Although it's a valid file, boost::filesystem::exists() throws + * an exception when checking it so we use this function as a special case. + */ +inline bool isLogPathWindowsNul(const std::string& path) { + return str::equalCaseInsensitive(path, kWindowsNUL); +} +#endif + } // namespace mongo::logv2