diff options
Diffstat (limited to 'source/Core/Communication.cpp')
-rw-r--r-- | source/Core/Communication.cpp | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/source/Core/Communication.cpp b/source/Core/Communication.cpp index ea84843..ae579d1 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); |