aboutsummaryrefslogtreecommitdiff
path: root/source/Core/Communication.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Core/Communication.cpp')
-rw-r--r--source/Core/Communication.cpp43
1 files changed, 37 insertions, 6 deletions
diff --git a/source/Core/Communication.cpp b/source/Core/Communication.cpp
index ea84843fe0b3..ae579d1b00ae 100644
--- a/source/Core/Communication.cpp
+++ b/source/Core/Communication.cpp
@@ -11,7 +11,6 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-private-log.h"
#include "lldb/Core/Communication.h"
#include "lldb/Core/Connection.h"
#include "lldb/Core/Log.h"
@@ -39,9 +38,11 @@ Communication::Communication(const char *name) :
Broadcaster (NULL, name),
m_connection_sp (),
m_read_thread_enabled (false),
+ m_read_thread_did_exit (false),
m_bytes(),
m_bytes_mutex (Mutex::eMutexTypeRecursive),
m_write_mutex (Mutex::eMutexTypeNormal),
+ m_synchronize_mutex (Mutex::eMutexTypeNormal),
m_callback (NULL),
m_callback_baton (NULL),
m_close_on_eof (true)
@@ -56,6 +57,7 @@ Communication::Communication(const char *name) :
SetEventName (eBroadcastBitReadThreadDidExit, "read thread did exit");
SetEventName (eBroadcastBitReadThreadShouldExit, "read thread should exit");
SetEventName (eBroadcastBitPacketAvailable, "packet available");
+ SetEventName (eBroadcastBitNoMorePendingInput, "no more pending input");
CheckInWithManager();
}
@@ -182,7 +184,8 @@ Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, Connectio
if (event_type & eBroadcastBitReadThreadDidExit)
{
- Disconnect (NULL);
+ if (GetCloseOnEOF ())
+ Disconnect (NULL);
break;
}
}
@@ -244,6 +247,7 @@ Communication::StartReadThread (Error *error_ptr)
snprintf(thread_name, sizeof(thread_name), "<lldb.comm.%s>", m_broadcaster_name.AsCString());
m_read_thread_enabled = true;
+ m_read_thread_did_exit = false;
m_read_thread = ThreadLauncher::LaunchThread(thread_name, Communication::ReadThread, this, error_ptr);
if (!m_read_thread.IsJoinable())
m_read_thread_enabled = false;
@@ -376,9 +380,8 @@ Communication::ReadThread (lldb::thread_arg_t p)
break;
case eConnectionStatusEndOfFile:
- if (comm->GetCloseOnEOF())
- done = true;
- break;
+ done = true;
+ break;
case eConnectionStatusError: // Check GetError() for details
if (error.GetType() == eErrorTypePOSIX && error.GetError() == EIO)
{
@@ -392,9 +395,13 @@ Communication::ReadThread (lldb::thread_arg_t p)
p,
Communication::ConnectionStatusAsCString (status));
break;
+ case eConnectionStatusInterrupted: // Synchronization signal from SynchronizeWithReadThread()
+ // The connection returns eConnectionStatusInterrupted only when there is no
+ // input pending to be read, so we can signal that.
+ comm->BroadcastEvent (eBroadcastBitNoMorePendingInput);
+ break;
case eConnectionStatusNoConnection: // No connection
case eConnectionStatusLostConnection: // Lost connection while connected to a valid connection
- case eConnectionStatusInterrupted: // Interrupted
done = true;
// Fall through...
case eConnectionStatusTimedOut: // Request timed out
@@ -410,7 +417,9 @@ Communication::ReadThread (lldb::thread_arg_t p)
if (log)
log->Printf ("%p Communication::ReadThread () thread exiting...", p);
+ comm->m_read_thread_did_exit = true;
// Let clients know that this thread is exiting
+ comm->BroadcastEvent (eBroadcastBitNoMorePendingInput);
comm->BroadcastEvent (eBroadcastBitReadThreadDidExit);
return NULL;
}
@@ -427,6 +436,28 @@ Communication::SetReadThreadBytesReceivedCallback
}
void
+Communication::SynchronizeWithReadThread ()
+{
+ // Only one thread can do the synchronization dance at a time.
+ Mutex::Locker locker(m_synchronize_mutex);
+
+ // First start listening for the synchronization event.
+ Listener listener("Communication::SyncronizeWithReadThread");
+ listener.StartListeningForEvents(this, eBroadcastBitNoMorePendingInput);
+
+ // If the thread is not running, there is no point in synchronizing.
+ if (!m_read_thread_enabled || m_read_thread_did_exit)
+ return;
+
+ // Notify the read thread.
+ m_connection_sp->InterruptRead();
+
+ // Wait for the synchronization event.
+ EventSP event_sp;
+ listener.WaitForEvent(NULL, event_sp);
+}
+
+void
Communication::SetConnection (Connection *connection)
{
Disconnect (NULL);