aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Core/Communication.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Core/Communication.cpp')
-rw-r--r--lldb/source/Core/Communication.cpp38
1 files changed, 25 insertions, 13 deletions
diff --git a/lldb/source/Core/Communication.cpp b/lldb/source/Core/Communication.cpp
index 0afd897a2093..b358e70b1a91 100644
--- a/lldb/source/Core/Communication.cpp
+++ b/lldb/source/Core/Communication.cpp
@@ -1,4 +1,4 @@
-//===-- Communication.cpp ---------------------------------------*- C++ -*-===//
+//===-- Communication.cpp -------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -71,8 +71,8 @@ Communication::~Communication() {
void Communication::Clear() {
SetReadThreadBytesReceivedCallback(nullptr, nullptr);
- Disconnect(nullptr);
StopReadThread(nullptr);
+ Disconnect(nullptr);
}
ConnectionStatus Communication::Connect(const char *url, Status *error_ptr) {
@@ -93,6 +93,8 @@ ConnectionStatus Communication::Disconnect(Status *error_ptr) {
LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMUNICATION),
"{0} Communication::Disconnect ()", this);
+ assert((!m_read_thread_enabled || m_read_thread_did_exit) &&
+ "Disconnecting while the read thread is running is racy!");
lldb::ConnectionSP connection_sp(m_connection_sp);
if (connection_sp) {
ConnectionStatus status = connection_sp->Disconnect(error_ptr);
@@ -315,16 +317,12 @@ lldb::thread_result_t Communication::ReadThread(lldb::thread_arg_t p) {
Status error;
ConnectionStatus status = eConnectionStatusSuccess;
bool done = false;
+ bool disconnect = false;
while (!done && comm->m_read_thread_enabled) {
size_t bytes_read = comm->ReadFromConnection(
buf, sizeof(buf), std::chrono::seconds(5), status, &error);
- if (bytes_read > 0)
+ if (bytes_read > 0 || status == eConnectionStatusEndOfFile)
comm->AppendBytesToCache(buf, bytes_read, true, status);
- else if ((bytes_read == 0) && status == eConnectionStatusEndOfFile) {
- if (comm->GetCloseOnEOF())
- comm->Disconnect();
- comm->AppendBytesToCache(buf, bytes_read, true, status);
- }
switch (status) {
case eConnectionStatusSuccess:
@@ -332,11 +330,12 @@ lldb::thread_result_t Communication::ReadThread(lldb::thread_arg_t p) {
case eConnectionStatusEndOfFile:
done = true;
+ disconnect = comm->GetCloseOnEOF();
break;
case eConnectionStatusError: // Check GetError() for details
if (error.GetType() == eErrorTypePOSIX && error.GetError() == EIO) {
// EIO on a pipe is usually caused by remote shutdown
- comm->Disconnect();
+ disconnect = comm->GetCloseOnEOF();
done = true;
}
if (error.Fail())
@@ -365,9 +364,22 @@ lldb::thread_result_t Communication::ReadThread(lldb::thread_arg_t p) {
if (log)
LLDB_LOGF(log, "%p Communication::ReadThread () thread exiting...", p);
- comm->m_read_thread_did_exit = true;
+ // Handle threads wishing to synchronize with us.
+ {
+ // Prevent new ones from showing up.
+ comm->m_read_thread_did_exit = true;
+
+ // Unblock any existing thread waiting for the synchronization signal.
+ comm->BroadcastEvent(eBroadcastBitNoMorePendingInput);
+
+ // Wait for the thread to finish...
+ std::lock_guard<std::mutex> guard(comm->m_synchronize_mutex);
+ // ... and disconnect.
+ if (disconnect)
+ comm->Disconnect();
+ }
+
// Let clients know that this thread is exiting
- comm->BroadcastEvent(eBroadcastBitNoMorePendingInput);
comm->BroadcastEvent(eBroadcastBitReadThreadDidExit);
return {};
}
@@ -399,10 +411,10 @@ void Communication::SynchronizeWithReadThread() {
listener_sp->GetEvent(event_sp, llvm::None);
}
-void Communication::SetConnection(Connection *connection) {
+void Communication::SetConnection(std::unique_ptr<Connection> connection) {
Disconnect(nullptr);
StopReadThread(nullptr);
- m_connection_sp.reset(connection);
+ m_connection_sp = std::move(connection);
}
const char *