JDevlieghere created this revision. JDevlieghere added reviewers: aprantl, augusto2112. Herald added a project: All. JDevlieghere requested review of this revision.
The Communication class was trying to (ab)use `unique_ptr's` atomic properties to protected it from concurrent access. Replace it with a regular reader/writer lock. https://reviews.llvm.org/D157159 Files: lldb/include/lldb/Core/Communication.h lldb/source/Core/Communication.cpp
Index: lldb/source/Core/Communication.cpp =================================================================== --- lldb/source/Core/Communication.cpp +++ lldb/source/Core/Communication.cpp @@ -27,8 +27,7 @@ using namespace lldb_private; Communication::Communication() - : m_connection_sp(), m_write_mutex(), m_close_on_eof(true) { -} + : m_connection_sp(), m_shared_mutex(), m_close_on_eof(true) {} Communication::~Communication() { Clear(); @@ -41,54 +40,46 @@ ConnectionStatus Communication::Connect(const char *url, Status *error_ptr) { Clear(); + std::unique_lock guard(m_shared_mutex); LLDB_LOG(GetLog(LLDBLog::Communication), "{0} Communication::Connect (url = {1})", this, url); - lldb::ConnectionSP connection_sp(m_connection_sp); - if (connection_sp) - return connection_sp->Connect(url, error_ptr); + if (m_connection_sp) + return m_connection_sp->Connect(url, error_ptr); if (error_ptr) error_ptr->SetErrorString("Invalid connection."); return eConnectionStatusNoConnection; } ConnectionStatus Communication::Disconnect(Status *error_ptr) { + std::unique_lock guard(m_shared_mutex); + LLDB_LOG(GetLog(LLDBLog::Communication), "{0} Communication::Disconnect ()", this); - lldb::ConnectionSP connection_sp(m_connection_sp); - if (connection_sp) { - ConnectionStatus status = connection_sp->Disconnect(error_ptr); - // We currently don't protect connection_sp with any mutex for multi- - // threaded environments. So lets not nuke our connection class without - // putting some multi-threaded protections in. We also probably don't want - // to pay for the overhead it might cause if every time we access the - // connection we have to take a lock. - // - // This unique pointer will cleanup after itself when this object goes - // away, so there is no need to currently have it destroy itself - // immediately upon disconnect. - // connection_sp.reset(); + if (m_connection_sp) { + ConnectionStatus status = m_connection_sp->Disconnect(error_ptr); return status; } return eConnectionStatusNoConnection; } bool Communication::IsConnected() const { - lldb::ConnectionSP connection_sp(m_connection_sp); - return (connection_sp ? connection_sp->IsConnected() : false); + std::shared_lock guard(m_shared_mutex); + return (m_connection_sp ? m_connection_sp->IsConnected() : false); } bool Communication::HasConnection() const { + std::shared_lock guard(m_shared_mutex); return m_connection_sp.get() != nullptr; } size_t Communication::Read(void *dst, size_t dst_len, const Timeout<std::micro> &timeout, ConnectionStatus &status, Status *error_ptr) { - Log *log = GetLog(LLDBLog::Communication); + std::shared_lock guard(m_shared_mutex); LLDB_LOG( - log, + GetLog(LLDBLog::Communication), "this = {0}, dst = {1}, dst_len = {2}, timeout = {3}, connection = {4}", this, dst, dst_len, timeout, m_connection_sp.get()); @@ -97,16 +88,20 @@ size_t Communication::Write(const void *src, size_t src_len, ConnectionStatus &status, Status *error_ptr) { - lldb::ConnectionSP connection_sp(m_connection_sp); + std::unique_lock guard(m_shared_mutex); + return WriteUnlocked(src, src_len, status, error_ptr); +} - std::lock_guard<std::mutex> guard(m_write_mutex); +size_t Communication::WriteUnlocked(const void *src, size_t src_len, + ConnectionStatus &status, + Status *error_ptr) { LLDB_LOG(GetLog(LLDBLog::Communication), "{0} Communication::Write (src = {1}, src_len = {2}" ") connection = {3}", - this, src, (uint64_t)src_len, connection_sp.get()); + this, src, (uint64_t)src_len, m_connection_sp.get()); - if (connection_sp) - return connection_sp->Write(src, src_len, status, error_ptr); + if (m_connection_sp) + return m_connection_sp->Write(src, src_len, status, error_ptr); if (error_ptr) error_ptr->SetErrorString("Invalid connection."); @@ -116,10 +111,12 @@ size_t Communication::WriteAll(const void *src, size_t src_len, ConnectionStatus &status, Status *error_ptr) { + std::unique_lock guard(m_shared_mutex); size_t total_written = 0; do - total_written += Write(static_cast<const char *>(src) + total_written, - src_len - total_written, status, error_ptr); + total_written += + WriteUnlocked(static_cast<const char *>(src) + total_written, + src_len - total_written, status, error_ptr); while (status == eConnectionStatusSuccess && total_written < src_len); return total_written; } @@ -128,6 +125,7 @@ const Timeout<std::micro> &timeout, ConnectionStatus &status, Status *error_ptr) { + std::shared_lock guard(m_shared_mutex); lldb::ConnectionSP connection_sp(m_connection_sp); if (connection_sp) return connection_sp->Read(dst, dst_len, timeout, status, error_ptr); Index: lldb/include/lldb/Core/Communication.h =================================================================== --- lldb/include/lldb/Core/Communication.h +++ lldb/include/lldb/Core/Communication.h @@ -15,7 +15,7 @@ #include "lldb/lldb-forward.h" #include "lldb/lldb-types.h" -#include <mutex> +#include <shared_mutex> #include <string> namespace lldb_private { @@ -165,10 +165,12 @@ void SetCloseOnEOF(bool b) { m_close_on_eof = b; } protected: + size_t WriteUnlocked(const void *src, size_t src_len, + lldb::ConnectionStatus &status, Status *error_ptr); + lldb::ConnectionSP m_connection_sp; ///< The connection that is current in use ///by this communications class. - std::mutex - m_write_mutex; ///< Don't let multiple threads write at the same time... + mutable std::shared_mutex m_shared_mutex; bool m_close_on_eof; size_t ReadFromConnection(void *dst, size_t dst_len,
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits