diff options
author | Billy Donahue <billy.donahue@mongodb.com> | 2022-05-13 04:01:14 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-05-13 04:58:26 +0000 |
commit | 95edbf51b92e6944043590fe781c901d2a815f9f (patch) | |
tree | f0c7e827152480a01f1485c11b4bbbb6f6ef078a /src | |
parent | 33ced84ad3537acb5a70907b6febb34adbcfbbcc (diff) | |
download | mongo-95edbf51b92e6944043590fe781c901d2a815f9f.tar.gz |
SERVER-63852 ThreadName rewrite
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/client.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/client.h | 2 | ||||
-rw-r--r-- | src/mongo/db/client_strand.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/client_strand.h | 6 | ||||
-rw-r--r-- | src/mongo/db/client_strand_test.cpp | 12 | ||||
-rw-r--r-- | src/mongo/logv2/log_source.h | 8 | ||||
-rw-r--r-- | src/mongo/util/concurrency/thread_name.cpp | 244 | ||||
-rw-r--r-- | src/mongo/util/concurrency/thread_name.h | 162 | ||||
-rw-r--r-- | src/mongo/util/errno_util.cpp | 18 | ||||
-rw-r--r-- | src/mongo/util/errno_util.h | 12 |
10 files changed, 272 insertions, 202 deletions
diff --git a/src/mongo/db/client.cpp b/src/mongo/db/client.cpp index 7da46be32df..acf26319b39 100644 --- a/src/mongo/db/client.cpp +++ b/src/mongo/db/client.cpp @@ -188,14 +188,14 @@ ThreadClient::ThreadClient(StringData desc, ServiceContext* serviceContext, transport::SessionHandle session) { invariantNoCurrentClient(); - _originalThreadName = ThreadName::get(ThreadContext::get()); + _originalThreadName = getThreadNameRef(); Client::initThread(desc, serviceContext, std::move(session)); } ThreadClient::~ThreadClient() { invariant(currentClient); currentClient.reset(nullptr); - ThreadName::set(ThreadContext::get(), _originalThreadName); + setThreadNameRef(std::move(_originalThreadName)); } Client* ThreadClient::get() const { diff --git a/src/mongo/db/client.h b/src/mongo/db/client.h index af203a5255e..9f566763a93 100644 --- a/src/mongo/db/client.h +++ b/src/mongo/db/client.h @@ -337,7 +337,7 @@ public: } private: - boost::intrusive_ptr<ThreadName> _originalThreadName; + ThreadNameRef _originalThreadName; }; /** diff --git a/src/mongo/db/client_strand.cpp b/src/mongo/db/client_strand.cpp index 41aa4af3d9e..f4bd5665540 100644 --- a/src/mongo/db/client_strand.cpp +++ b/src/mongo/db/client_strand.cpp @@ -69,7 +69,7 @@ void ClientStrand::_setCurrent() noexcept { Client::setCurrent(std::move(_client)); // Set up the thread name. - _oldThreadName = ThreadName::set(ThreadContext::get(), _threadName); + _oldThreadName = setThreadNameRef(_threadName); if (_oldThreadName) { LOGV2_DEBUG(5127802, kDiagnosticLogLevel, "Set thread name", "name"_attr = *_threadName); } @@ -85,10 +85,10 @@ void ClientStrand::_releaseCurrent() noexcept { if (_oldThreadName) { // Reset the last thread name because it was previously set in the OS. - ThreadName::set(ThreadContext::get(), std::move(_oldThreadName)); + setThreadNameRef(std::move(_oldThreadName)); } else { // Release the thread name for reuse. - ThreadName::release(ThreadContext::get()); + releaseThreadNameRef(); } LOGV2_DEBUG( diff --git a/src/mongo/db/client_strand.h b/src/mongo/db/client_strand.h index cab3140671d..334e29a7c15 100644 --- a/src/mongo/db/client_strand.h +++ b/src/mongo/db/client_strand.h @@ -133,7 +133,7 @@ public: ClientStrand(ServiceContext::UniqueClient client) : _clientPtr(client.get()), _client(std::move(client)), - _threadName(make_intrusive<ThreadName>(_client->desc())) {} + _threadName(ThreadNameRef{_client->desc()}) {} /** * Get a pointer to the underlying Client. @@ -204,8 +204,8 @@ private: ServiceContext::UniqueClient _client; - boost::intrusive_ptr<ThreadName> _threadName; - boost::intrusive_ptr<ThreadName> _oldThreadName; + ThreadNameRef _threadName; + ThreadNameRef _oldThreadName; }; inline void ClientStrand::Executor::schedule(Task task) { diff --git a/src/mongo/db/client_strand_test.cpp b/src/mongo/db/client_strand_test.cpp index cce87321862..661b03ea8cd 100644 --- a/src/mongo/db/client_strand_test.cpp +++ b/src/mongo/db/client_strand_test.cpp @@ -54,7 +54,7 @@ public: * Clean up any leftover thread_local pieces. */ void releaseClient() { - ThreadName::release(ThreadContext::get()); + releaseThreadNameRef(); if (haveClient()) { Client::releaseCurrent(); } @@ -123,7 +123,7 @@ TEST_F(ClientStrandTest, BindMultipleTimes) { // We have no bound Client. assertStrandNotBound(strand); - for (auto i = 0; i < 100; ++i) { + for (auto i = 0; i < 10; ++i) { // Bind a bunch of times. { @@ -145,7 +145,7 @@ TEST_F(ClientStrandTest, BindMultipleTimesAndDismiss) { assertStrandNotBound(strand); auto guard = strand->bind(); - for (auto i = 0; i < 100; ++i) { + for (auto i = 0; i < 10; ++i) { assertStrandBound(strand); // Dismiss the current guard. @@ -266,7 +266,7 @@ TEST_F(ClientStrandTest, BindLocalAfterWorkerThread) { TEST_F(ClientStrandTest, BindManyWorkerThreads) { auto strand = ClientStrand::make(getServiceContext()->makeClient(kClientName1)); - constexpr size_t kCount = 100; + constexpr size_t kCount = 10; auto barrier = std::make_shared<unittest::Barrier>(kCount); size_t threadsBound = 0; @@ -308,7 +308,7 @@ TEST_F(ClientStrandTest, SwapStrands) { assertStrandNotBound(strand1); assertStrandNotBound(strand2); - for (size_t i = 0; i < 100; ++i) { + for (size_t i = 0; i < 10; ++i) { // Alternate between binding strand1 and strand2. Start on strand2 so it has a different // thread name than the previous test. auto& strand = (i % 2 == 0) ? strand2 : strand1; @@ -325,7 +325,7 @@ TEST_F(ClientStrandTest, SwapStrands) { } TEST_F(ClientStrandTest, Executor) { - constexpr size_t kCount = 100; + constexpr size_t kCount = 10; auto strand = ClientStrand::make(getServiceContext()->makeClient(kClientName1)); diff --git a/src/mongo/logv2/log_source.h b/src/mongo/logv2/log_source.h index 4051bcfb55a..8e83cb6ad54 100644 --- a/src/mongo/logv2/log_source.h +++ b/src/mongo/logv2/log_source.h @@ -74,10 +74,10 @@ public: add_attribute_unlocked(attributes::timeStamp(), boost::log::attributes::make_function([]() { return Date_t::now(); })); - add_attribute_unlocked( - attributes::threadName(), boost::log::attributes::make_function([isShutdown]() { - return isShutdown ? "shutdown"_sd : ThreadName::getStaticString(); - })); + add_attribute_unlocked(attributes::threadName(), + boost::log::attributes::make_function([isShutdown]() { + return isShutdown ? "shutdown"_sd : getThreadName(); + })); } explicit LogSource(const LogDomain::Internal* domain) : LogSource(domain, false) {} diff --git a/src/mongo/util/concurrency/thread_name.cpp b/src/mongo/util/concurrency/thread_name.cpp index 7f21b5bcc56..36f8e24f577 100644 --- a/src/mongo/util/concurrency/thread_name.cpp +++ b/src/mongo/util/concurrency/thread_name.cpp @@ -27,9 +27,6 @@ * it in the license file. */ - -#include "mongo/platform/basic.h" - #include "mongo/util/concurrency/thread_name.h" #if defined(__APPLE__) || defined(__linux__) @@ -43,10 +40,6 @@ #include <mach/thread_info.h> #endif #endif -#if defined(__linux__) -#include <sys/syscall.h> -#include <sys/types.h> -#endif #include <fmt/format.h> @@ -54,7 +47,8 @@ #include "mongo/config.h" #include "mongo/logv2/log.h" #include "mongo/platform/atomic_word.h" -#include "mongo/util/str.h" +#include "mongo/platform/process_id.h" +#include "mongo/util/thread_context.h" #define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kControl @@ -64,6 +58,10 @@ using namespace fmt::literals; namespace { +bool isMainThread() { + return ProcessId::getCurrent() == ProcessId::getCurrentThreadId(); +} + #ifdef _WIN32 // From https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx // Note: The thread name is only set for the thread if the debugger is attached. @@ -94,49 +92,15 @@ void setWindowsThreadName(DWORD dwThreadID, const char* threadName) { } #endif -constexpr auto kMainId = size_t{0}; - -auto makeAnonymousThreadName() { - static auto gNextAnonymousId = AtomicWord<size_t>{kMainId}; - auto id = gNextAnonymousId.fetchAndAdd(1); - if (id == kMainId) { - // The first thread name should always be "main". - return make_intrusive<ThreadName>("main"); - } else { - return make_intrusive<ThreadName>("thread{}"_format(id)); - } -} - -struct ThreadNameSconce { - ThreadNameSconce() : cachedPtr(makeAnonymousThreadName()) { - // Note that we're not setting the thread name here. It will log differently, but appear the - // same in top and like. - } - - // At any given time, either cachedPtr or activePtr can be valid, but not both. - boost::intrusive_ptr<ThreadName> activePtr; - boost::intrusive_ptr<ThreadName> cachedPtr; -}; - -auto getSconce = ThreadContext::declareDecoration<ThreadNameSconce>(); -auto& getThreadName(const boost::intrusive_ptr<ThreadContext>& context) { - auto& sconce = getSconce(context.get()); - if (sconce.activePtr) { - return sconce.activePtr; - } - - return sconce.cachedPtr; -} - -void setOSThreadName(StringData threadName) { +void setOSThreadName(const std::string& threadName) { #if defined(_WIN32) // Naming should not be expensive compared to thread creation and connection set up, but if // testing shows otherwise we should make this depend on DEBUG again. - setWindowsThreadName(GetCurrentThreadId(), threadName.rawData()); + setWindowsThreadName(GetCurrentThreadId(), threadName.c_str()); #elif defined(__APPLE__) // Maximum thread name length on OS X is MAXTHREADNAMESIZE (64 characters). This assumes // OS X 10.6 or later. - std::string threadNameCopy = threadName.toString(); + std::string threadNameCopy = threadName; if (threadNameCopy.size() > MAXTHREADNAMESIZE) { threadNameCopy.resize(MAXTHREADNAMESIZE - 4); threadNameCopy += "..."; @@ -152,95 +116,137 @@ void setOSThreadName(StringData threadName) { // Do not set thread name on the main() thread. Setting the name on main thread breaks // pgrep/pkill since these programs base this name on /proc/*/status which displays the thread // name, not the executable name. - if (getpid() != syscall(SYS_gettid)) { - // Maximum thread name length supported on Linux is 16 including the null terminator. - // Ideally we use short and descriptive thread names that fit: this helps for log - // readability as well. Still, as the limit is so low and a few current names exceed the - // limit, it's best to shorten long names. - int error = 0; - if (threadName.size() > 15) { - std::string shortName = str::stream() - << threadName.substr(0, 7) << '.' << threadName.substr(threadName.size() - 7); - error = pthread_setname_np(pthread_self(), shortName.c_str()); - } else { - error = pthread_setname_np(pthread_self(), threadName.rawData()); - } - - if (error) { - LOGV2(23103, - "Ignoring error from setting thread name: {error}", - "Ignoring error from setting thread name", - "error"_attr = errorMessage(posixError(error))); - } + if (isMainThread()) + return; + // Maximum thread name length supported on Linux is 16 including the null terminator. + // Ideally we use short and descriptive thread names that fit: this helps for log + // readability as well. Still, as the limit is so low and a few current names exceed the + // limit, it's best to shorten long names. + static constexpr size_t kMaxThreadNameLength = 16 - 1; + boost::optional<std::string> shortNameBuf; + const char* truncName = threadName.c_str(); + if (threadName.size() > kMaxThreadNameLength) { + StringData sd = threadName; + shortNameBuf = "{}.{}"_format(sd.substr(0, 7), sd.substr(sd.size() - 7)); + truncName = shortNameBuf->c_str(); } -#endif -} - -} // namespace -ThreadName::Id ThreadName::_nextId() { - static auto gNextId = AtomicWord<Id>{0}; - return gNextId.fetchAndAdd(1); + int error = pthread_setname_np(pthread_self(), truncName); + if (auto ec = posixError(error)) { + LOGV2(23103, + "Ignoring error from setting thread name: {error}", + "Ignoring error from setting thread name", + "error"_attr = errorMessage(ec)); + } +#endif } -StringData ThreadName::getStaticString() { - auto& context = ThreadContext::get(); - if (!context) { - // Use a static fallback to avoid allocations. This is the string that will be used before - // initializers run in main a.k.a. pre-init. - static constexpr auto kFallback = "-"_sd; - return kFallback; +/** + * Manages the relationship of our high-level ThreadNameRef strings to + * the thread local context, and efficiently notifying the OS of name + * changes. We try to apply temporary names to threads to make them + * meaningful representations of the kind of work the thread is doing. + * But sharing these names with the OS is slow and name length is limited. So + * ThreadNameInfo is an auxiliary resource to the OS thread name, available to + * the LOGV2 system and to GDB. + * + * ThreadNameInfo is a decoration of ThreadContext. + * ThreadContext are held by thread_local storage and so threads started + * after server initialization will have an associated ThreadNameInfo. + * + * A name is "active" when it has been pushed to the OS by `setHandle`. The + * association can be abandoned by calling `release`. This doesn't affect the + * OS, but indicates that the name binding is abandoned and shouldn't be + * preserved by returning it from subsequent `setHandle` calls. We do however + * retain the inactive reference in hopes of perhaps identifying redundant + * `setHandle` calls that would set the OS thread name to the same value it + * already has. + * + * Upon construction, a ThreadNameInfo has an inactive unique name that + * the OS doesn't know about yet. A push/pop style call sequence of + * `h=getHandle()` then (eventually) `setHandle(h)` can make this name + * the active (known to the OS) thread name. + */ +class ThreadNameInfo { +public: + /** Returns the thread name ref, whether it's active or not. */ + const ThreadNameRef& getHandle() const { + return _h; } - return getThreadName(context)->toString(); -} + /** + * Changes the thread name ref to `name`, marking it active, + * and updating the OS thread name if necessary. + * + * If there was a previous active thread name, it is returned so that + * callers can perhaps restore it and implement a temporary rename. + * Inactive thread names are considered abandoned and are not returned. + */ + ThreadNameRef setHandle(ThreadNameRef name) { + bool alreadyActive = std::exchange(_active, true); + if (name == _h) + return {}; + auto old = std::exchange(_h, std::move(name)); + setOSThreadName(*_h); + if (alreadyActive) + return old; + return {}; + } -boost::intrusive_ptr<ThreadName> ThreadName::get(boost::intrusive_ptr<ThreadContext> context) { - return getThreadName(context); -} + /** + * Mark the current ThreadNameRef as inactive. This is only a marking and + * does not affect the OS thread name. The ThreadNameRef is retained + * so that redundant setHandle calls can be recognized and elided. + */ + void release() { + _active = false; + } -boost::intrusive_ptr<ThreadName> ThreadName::set(boost::intrusive_ptr<ThreadContext> context, - boost::intrusive_ptr<ThreadName> name) { - invariant(name); + /** + * Get a pointer to this thread's ThreadNameInfo. + * Returns null if there's no ThreadContext to get it from. + */ + static ThreadNameInfo* forThisThread() { + auto& context = ThreadContext::get(); + return context ? &_decoration(*context) : nullptr; + } - auto& sconce = getSconce(context.get()); +private: + inline static auto _decoration = ThreadContext::declareDecoration<ThreadNameInfo>(); + + /** + * Main thread always gets "main". Other threads are sequentially + * named as "thread1", "thread2", etc. + */ + static std::string _makeAnonymousThreadName() { + if (isMainThread()) + return "main"; + static AtomicWord<uint64_t> next{1}; + return "thread{}"_format(next.fetchAndAdd(1)); + } - if (sconce.activePtr) { - invariant(!sconce.cachedPtr); - if (*sconce.activePtr == *name) { - // The name was already set, skip setting it to the OS thread name. - return {}; - } else { - // Replace the current active name with the new one, and set the OS thread name. - setOSThreadName(name->toString()); - return std::exchange(sconce.activePtr, name); - } - } else if (sconce.cachedPtr) { - if (*sconce.cachedPtr == *name) { - // The name was cached, set it as active and skip setting it to the OS thread name. - sconce.activePtr = std::exchange(sconce.cachedPtr, {}); - return {}; - } else { - // The new name is different than the cached name, set the active, reset the cached, and - // set the OS thread name. - setOSThreadName(name->toString()); + ThreadNameRef _h{_makeAnonymousThreadName()}; + bool _active = false; +}; - sconce.activePtr = name; - sconce.cachedPtr.reset(); - return {}; - } - } +} // namespace - MONGO_UNREACHABLE; +ThreadNameRef getThreadNameRef() { + if (auto info = ThreadNameInfo::forThisThread()) + return info->getHandle(); + return {}; } -void ThreadName::release(boost::intrusive_ptr<ThreadContext> context) { - auto& sconce = getSconce(context.get()); - if (sconce.activePtr) { - sconce.cachedPtr = std::exchange(sconce.activePtr, {}); - } +ThreadNameRef setThreadNameRef(ThreadNameRef name) { + invariant(name); + if (auto info = ThreadNameInfo::forThisThread()) + return info->setHandle(std::move(name)); + return {}; } -ThreadName::ThreadName(StringData name) : _id(_nextId()), _storage(name.toString()){}; +void releaseThreadNameRef() { + if (auto info = ThreadNameInfo::forThisThread()) + info->release(); +} } // namespace mongo diff --git a/src/mongo/util/concurrency/thread_name.h b/src/mongo/util/concurrency/thread_name.h index 2efd004263a..f4bc4582a3c 100644 --- a/src/mongo/util/concurrency/thread_name.h +++ b/src/mongo/util/concurrency/thread_name.h @@ -29,103 +29,141 @@ #pragma once +#include <memory> #include <string> #include "mongo/base/string_data.h" -#include "mongo/util/intrusive_counter.h" -#include "mongo/util/thread_context.h" +#include "mongo/util/static_immortal.h" namespace mongo { /** - * ThreadName is a uniquely identifyable, immutable, ref-counted string. + * A nullable handle pinning a ref-counted immutable string. + * Copies of a ThreadNameString refer to the same string object. + * Equality comparisons consider only that string's identity, not its value. + * + * This class is just a kind of refcounted string handle and does not itself + * interact with the OS or with thread storage. + * + * Presents a pointer-like API with `get()`, and dereference operators, and + * explicit bool conversion. Dereferencing yields a reference to a + * string value if nonempty. Dereferencing an empty reference is allowed and + * yields the singleton string value "-". + * + * Copyable and movable, with the usual refcounting semantics. Copies refer + * to the same string and will compare equal to each other. * - * This class is used for three purposes: - * - Setting the official thread name with the OS. - * - Populating the "ctx" field for log lines. - * - Providing a thread name to gdb. */ -class ThreadName : public RefCountable { +class ThreadNameRef { public: - using Id = size_t; + /** An empty ref (empty refs still stringify as "-"). */ + ThreadNameRef() = default; - /** - * Create a new instance. - * - * Note that this does not set it to be the official one for the thread. - */ - explicit ThreadName(StringData name); - ThreadName(const ThreadName&) = delete; - ThreadName(ThreadName&&) = delete; + /** A ref to the string value `name`. */ + explicit ThreadNameRef(std::string name) + : _ptr{std::make_shared<std::string>(std::move(name))} {} /** - * Get the official ThreadName for the current thread via the ThreadContext. + * Dereferences this. If nonempty, returns its string value. + * Otherwise, returns a singleton "-" string. */ - static boost::intrusive_ptr<ThreadName> get(boost::intrusive_ptr<ThreadContext> context); + const std::string* get() const { + if (_ptr) + return &*_ptr; + static const StaticImmortal whenEmpty = std::string("-"); + return &*whenEmpty; + } - /** - * Set the official ThreadName for the current thread via the ThreadContext. - * - * Note that this also will set the OS thread name if the name is different from the current - * one. - * - * If a different non-anonymous thread name was previously set, this returns that name. If the - * given name was already set, a previous name was released, or the initial name was set, this - * returns an empty pointer. - */ - static boost::intrusive_ptr<ThreadName> set(boost::intrusive_ptr<ThreadContext> context, - boost::intrusive_ptr<ThreadName> name); + const std::string* operator->() const { + return get(); + } - /** - * Release the current thread name. - * - * This does not unset the OS thread name or change the current storage. Instead, this marks the - * current name as available for reuse or replacement. - */ - static void release(boost::intrusive_ptr<ThreadContext> context); + const std::string& operator*() const { + return *get(); + } - /** - * Get a string for the current thread without new allocations. - * - * In pre-init, this returns "-". That value will mostly be associated with the main thread. - * If a thread is somehow started in pre-init and dodges our ThreadSafetyContext checks, it will - * also return "-" for this function. - */ - static StringData getStaticString(); + /** Returns true if nonempty. */ + explicit operator bool() const { + return !!_ptr; + } - StringData toString() const { - return _storage; + operator StringData() const { + return **this; } - friend bool operator==(const ThreadName& lhs, const ThreadName& rhs) noexcept { - return lhs._id == rhs._id; + /** + * Two ThreadNameRef are equal if and only if they are copies of the same + * original ThreadNameRef object. Equality of string value is insufficient. + */ + friend bool operator==(const ThreadNameRef& a, const ThreadNameRef& b) noexcept { + return a._ptr == b._ptr; } - friend bool operator!=(const ThreadName& lhs, const ThreadName& rhs) noexcept { - return lhs._id != rhs._id; + friend bool operator!=(const ThreadNameRef& a, const ThreadNameRef& b) noexcept { + return !(a == b); } private: - static Id _nextId(); - - const Id _id; - const std::string _storage; + std::shared_ptr<const std::string> _ptr; }; /** + * Returns the name reference attached to current thread. Returns an empty + * ThreadNameRef if current thread has no ThreadContext. The empty ThreadNameRef + * still has a valid string value of "-". + * + * This string is not limited in length, so it will be a better name + * than the name the OS uses to refer to the same thread. + */ +ThreadNameRef getThreadNameRef(); + +/** + * Swaps in a new active name, returns the old one if it was active. + * + * The active thread name is used for: + * - Setting the thread name in the OS. As an optimization, clearing + * the thread name in the OS is performed lazily. + * - Populating the "ctx" field for log lines. + * - Providing a thread name to GDB. + * + * Has no effect if there is no `ThreadContext` for this thread. + */ +ThreadNameRef setThreadNameRef(ThreadNameRef name); + +/** + * Marks the ThreadNameRef attached to the current thread as inactive. + * - The inactive thread name remains attached to the thread. + * - The thread name according to the OS is not changed. + * - A subsequent `setThreadNameRef` call will not return it. + * - An immediately subsequent `setThreadNameRef` call with the same name will + * cheaply reactivate it, saving two OS thread rename operations. + * This is an optimization on the assumption that a thread name will be + * temporarily set to the same `ThreadNameRef` repeatedly, so setting it and + * resetting it with the OS on each change would be wasteful. + * + * Has no effect if there is no `ThreadContext` for this thread. + */ +void releaseThreadNameRef(); + +/** * Sets the name of the current thread. */ -inline void setThreadName(StringData name) { - ThreadName::set(ThreadContext::get(), make_intrusive<ThreadName>(name)); +inline void setThreadName(std::string name) { + setThreadNameRef(ThreadNameRef{std::move(name)}); } /** - * Retrieves the name of the current thread, as previously set, or "thread#" if no name was - * previously set. The returned StringData is always null terminated so it is safe to pass to APIs - * that expect c-strings. + * Returns current thread's name, as previously set, or "main", or + * "thread#" if no name was previously set. + * + * Before the ThreadContext API is initialized, this returns "-". That value + * will mostly be associated with the main thread, or threads that were started + * before ThreadContext API initialization. + * + * Used by the MongoDB GDB pretty printer extentions in `gdb/mongo.py`. */ inline StringData getThreadName() { - return ThreadName::get(ThreadContext::get())->toString(); + return *getThreadNameRef(); } } // namespace mongo diff --git a/src/mongo/util/errno_util.cpp b/src/mongo/util/errno_util.cpp index a9c326f3ae8..9f4ad2611dd 100644 --- a/src/mongo/util/errno_util.cpp +++ b/src/mongo/util/errno_util.cpp @@ -27,12 +27,19 @@ * it in the license file. */ +#include "mongo/platform/basic.h" + #include "mongo/util/errno_util.h" #include <cerrno> #include <fmt/format.h> #include <system_error> +#ifdef _WIN32 +#include <errhandlingapi.h> +#include <winsock2.h> +#endif + #ifndef _WIN32 #include <netdb.h> #endif @@ -41,6 +48,17 @@ namespace mongo { using namespace fmt::literals; +#ifdef _WIN32 +namespace errno_util_win32_detail { +int gle() { + return GetLastError(); +} +int wsaGle() { + return WSAGetLastError(); +} +} // namespace errno_util_win32_detail +#endif + class AddrInfoErrorCategory : public std::error_category { public: const char* name() const noexcept override { diff --git a/src/mongo/util/errno_util.h b/src/mongo/util/errno_util.h index 408cebf528c..18b879e704a 100644 --- a/src/mongo/util/errno_util.h +++ b/src/mongo/util/errno_util.h @@ -29,6 +29,7 @@ #pragma once +#include <cstdlib> #include <system_error> #include <utility> @@ -36,6 +37,13 @@ namespace mongo { +#ifdef _WIN32 +namespace errno_util_win32_detail { +int gle(); +int wsaGle(); +} // namespace errno_util_win32_detail +#endif + /** * Returns category to use for POSIX errno error codes. * On POSIX, `errno` codes are the `std::system_category`. @@ -86,7 +94,7 @@ inline std::error_code lastPosixError() { */ inline std::error_code lastSystemError() { #ifdef _WIN32 - return systemError(GetLastError()); + return systemError(errno_util_win32_detail::gle()); #else return systemError(errno); #endif @@ -123,7 +131,7 @@ inline std::error_code addrInfoError(int e) { */ inline std::error_code lastSocketError() { #ifdef _WIN32 - return systemError(WSAGetLastError()); + return systemError(errno_util_win32_detail::wsaGle()); #else return lastSystemError(); #endif |