diff options
-rw-r--r-- | src/mongo/util/log.cpp | 84 | ||||
-rw-r--r-- | src/mongo/util/log.h | 1 | ||||
-rw-r--r-- | src/mongo/util/processinfo.cpp | 15 |
3 files changed, 65 insertions, 35 deletions
diff --git a/src/mongo/util/log.cpp b/src/mongo/util/log.cpp index 75720dbcf7f..b3c130bf264 100644 --- a/src/mongo/util/log.cpp +++ b/src/mongo/util/log.cpp @@ -54,6 +54,11 @@ using namespace std; namespace mongo { +namespace { +const char kUnknownMsg[] = "Unknown error"; +const int kBuflen = 256; // strerror strings in non-English locales can be large. +} + static logger::ExtraLogContextFn _appendExtraLogContext; Status logger::registerExtraLogContextFn(logger::ExtraLogContextFn contextFn) { @@ -81,50 +86,69 @@ bool rotateLogs(bool renameFiles) { return result.empty(); } -string errnoWithDescription(int x) { +string errnoWithDescription(int errNumber) { #if defined(_WIN32) - if (x < 0) - x = GetLastError(); + if (errNumber < 0) + errNumber = GetLastError(); #else - if (x < 0) - x = errno; + if (errNumber < 0) + errNumber = errno; #endif - stringstream s; - s << "errno:" << x << ' '; -#if defined(_WIN32) - LPWSTR errorText = NULL; + char buf[kBuflen]; + char* msg{nullptr}; + +#if defined(__GNUC__) && defined(_GNU_SOURCE) + msg = strerror_r(errNumber, buf, kBuflen); +#elif defined(_WIN32) + + LPWSTR errorText = nullptr; FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - x, + nullptr, + errNumber, 0, reinterpret_cast<LPWSTR>(&errorText), // output 0, // minimum size for output buffer - NULL); + nullptr); + if (errorText) { - string x = toUtf8String(errorText); - for (string::iterator i = x.begin(); i != x.end(); i++) { - if (*i == '\n' || *i == '\r') - break; - s << *i; + string utf8ErrorText = toUtf8String(errorText); + auto size = utf8ErrorText.find_first_of("\r\n"); + if (size == string::npos) { // not found + size = utf8ErrorText.length(); + } + + if (size > kBuflen) { + size = kBuflen; } + + memcpy(buf, utf8ErrorText.c_str(), size); + msg = buf; LocalFree(errorText); - } else - s << strerror(x); -/* -DWORD n = FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, x, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, 0, NULL); -*/ + } else if (strerror_s(buf, kBuflen, errNumber) != 0) { + msg = buf; + } +#else /* XSI strerror_r */ + if (strerror_r(errNumber, buf, kBuflen) == 0) { + msg = buf; + } +#endif + + if (!msg) { + return {kUnknownMsg}; + } + + return {msg}; +} + +std::pair<int, std::string> errnoAndDescription() { +#if defined(_WIN32) + int errNumber = GetLastError(); #else - s << strerror(x); + int errNumber = errno; #endif - return s.str(); + return {errNumber, errnoWithDescription(errNumber)}; } void logContext(const char* errmsg) { diff --git a/src/mongo/util/log.h b/src/mongo/util/log.h index b0f53a30b87..82a78b3cf99 100644 --- a/src/mongo/util/log.h +++ b/src/mongo/util/log.h @@ -217,6 +217,7 @@ extern Tee* const warnings; // Things put here go in serverStatus extern Tee* const startupWarningsLog; // Things put here get reported in MMS std::string errnoWithDescription(int errorcode = -1); +std::pair<int, std::string> errnoAndDescription(); /** * Write the current context (backtrace), along with the optional "msg". diff --git a/src/mongo/util/processinfo.cpp b/src/mongo/util/processinfo.cpp index 5a0e8dc798c..8afcb2f0eeb 100644 --- a/src/mongo/util/processinfo.cpp +++ b/src/mongo/util/processinfo.cpp @@ -58,6 +58,15 @@ public: path = p; ofstream out(path.c_str(), ios_base::out); out << ProcessId::getCurrent() << endl; + if (!out.good()) { + auto errAndStr = errnoAndDescription(); + if (errAndStr.first == 0) { + log() << "ERROR: Cannot write pid file to " << path + << ": Unable to determine OS error"; + } else { + log() << "ERROR: Cannot write pid file to " << path << ": " << errAndStr.second; + } + } return out.good(); } @@ -65,11 +74,7 @@ public: } pidFileWiper; bool writePidFile(const string& path) { - bool e = pidFileWiper.write(path); - if (!e) { - log() << "ERROR: Cannot write pid file to " << path << ": " << strerror(errno); - } - return e; + return pidFileWiper.write(path); } ProcessInfo::SystemInfo* ProcessInfo::systemInfo = NULL; |