1 //===-- Communication.cpp ---------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
12 // Other libraries and framework includes
14 #include "lldb/Core/Communication.h"
15 #include "lldb/Core/Connection.h"
16 #include "lldb/Core/Log.h"
17 #include "lldb/Core/Timer.h"
18 #include "lldb/Core/Event.h"
19 #include "lldb/Host/Host.h"
20 #include "lldb/Host/HostThread.h"
21 #include "lldb/Host/ThreadLauncher.h"
25 using namespace lldb_private;
28 Communication::GetStaticBroadcasterClass ()
30 static ConstString class_name ("lldb.communication");
34 //----------------------------------------------------------------------
36 //----------------------------------------------------------------------
37 Communication::Communication(const char *name) :
38 Broadcaster (NULL, name),
40 m_read_thread_enabled (false),
41 m_read_thread_did_exit (false),
43 m_bytes_mutex (Mutex::eMutexTypeRecursive),
44 m_write_mutex (Mutex::eMutexTypeNormal),
45 m_synchronize_mutex (Mutex::eMutexTypeNormal),
47 m_callback_baton (NULL),
51 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
52 "%p Communication::Communication (name = %s)",
55 SetEventName (eBroadcastBitDisconnected, "disconnected");
56 SetEventName (eBroadcastBitReadThreadGotBytes, "got bytes");
57 SetEventName (eBroadcastBitReadThreadDidExit, "read thread did exit");
58 SetEventName (eBroadcastBitReadThreadShouldExit, "read thread should exit");
59 SetEventName (eBroadcastBitPacketAvailable, "packet available");
60 SetEventName (eBroadcastBitNoMorePendingInput, "no more pending input");
65 //----------------------------------------------------------------------
67 //----------------------------------------------------------------------
68 Communication::~Communication()
70 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
71 "%p Communication::~Communication (name = %s)",
72 this, m_broadcaster_name.AsCString(""));
77 Communication::Clear()
79 SetReadThreadBytesReceivedCallback (NULL, NULL);
81 StopReadThread (NULL);
85 Communication::Connect (const char *url, Error *error_ptr)
89 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Connect (url = %s)", this, url);
91 lldb::ConnectionSP connection_sp (m_connection_sp);
92 if (connection_sp.get())
93 return connection_sp->Connect (url, error_ptr);
95 error_ptr->SetErrorString("Invalid connection.");
96 return eConnectionStatusNoConnection;
100 Communication::Disconnect (Error *error_ptr)
102 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Disconnect ()", this);
104 lldb::ConnectionSP connection_sp (m_connection_sp);
105 if (connection_sp.get())
107 ConnectionStatus status = connection_sp->Disconnect (error_ptr);
108 // We currently don't protect connection_sp with any mutex for
109 // multi-threaded environments. So lets not nuke our connection class
110 // without putting some multi-threaded protections in. We also probably
111 // don't want to pay for the overhead it might cause if every time we
112 // access the connection we have to take a lock.
114 // This unique pointer will cleanup after itself when this object goes away,
115 // so there is no need to currently have it destroy itself immediately
117 //connection_sp.reset();
120 return eConnectionStatusNoConnection;
124 Communication::IsConnected () const
126 lldb::ConnectionSP connection_sp (m_connection_sp);
127 if (connection_sp.get())
128 return connection_sp->IsConnected ();
133 Communication::HasConnection () const
135 return m_connection_sp.get() != NULL;
139 Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr)
141 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
142 "%p Communication::Read (dst = %p, dst_len = %" PRIu64 ", timeout = %u usec) connection = %p",
147 m_connection_sp.get());
149 if (m_read_thread_enabled)
151 // We have a dedicated read thread that is getting data for us
152 size_t cached_bytes = GetCachedBytes (dst, dst_len);
153 if (cached_bytes > 0 || timeout_usec == 0)
155 status = eConnectionStatusSuccess;
159 if (m_connection_sp.get() == NULL)
162 error_ptr->SetErrorString("Invalid connection.");
163 status = eConnectionStatusNoConnection;
166 // Set the timeout appropriately
167 TimeValue timeout_time;
168 if (timeout_usec != UINT32_MAX)
170 timeout_time = TimeValue::Now();
171 timeout_time.OffsetWithMicroSeconds (timeout_usec);
174 Listener listener ("Communication::Read");
175 listener.StartListeningForEvents (this, eBroadcastBitReadThreadGotBytes | eBroadcastBitReadThreadDidExit);
177 while (listener.WaitForEvent (timeout_time.IsValid() ? &timeout_time : NULL, event_sp))
179 const uint32_t event_type = event_sp->GetType();
180 if (event_type & eBroadcastBitReadThreadGotBytes)
182 return GetCachedBytes (dst, dst_len);
185 if (event_type & eBroadcastBitReadThreadDidExit)
187 if (GetCloseOnEOF ())
195 // We aren't using a read thread, just read the data synchronously in this
197 lldb::ConnectionSP connection_sp (m_connection_sp);
198 if (connection_sp.get())
200 return connection_sp->Read (dst, dst_len, timeout_usec, status, error_ptr);
204 error_ptr->SetErrorString("Invalid connection.");
205 status = eConnectionStatusNoConnection;
211 Communication::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr)
213 lldb::ConnectionSP connection_sp (m_connection_sp);
215 Mutex::Locker locker(m_write_mutex);
216 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
217 "%p Communication::Write (src = %p, src_len = %" PRIu64 ") connection = %p",
221 connection_sp.get());
223 if (connection_sp.get())
224 return connection_sp->Write (src, src_len, status, error_ptr);
227 error_ptr->SetErrorString("Invalid connection.");
228 status = eConnectionStatusNoConnection;
234 Communication::StartReadThread (Error *error_ptr)
239 if (m_read_thread.IsJoinable())
242 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
243 "%p Communication::StartReadThread ()", this);
246 char thread_name[1024];
247 snprintf(thread_name, sizeof(thread_name), "<lldb.comm.%s>", m_broadcaster_name.AsCString());
249 m_read_thread_enabled = true;
250 m_read_thread_did_exit = false;
251 m_read_thread = ThreadLauncher::LaunchThread(thread_name, Communication::ReadThread, this, error_ptr);
252 if (!m_read_thread.IsJoinable())
253 m_read_thread_enabled = false;
254 return m_read_thread_enabled;
258 Communication::StopReadThread (Error *error_ptr)
260 if (!m_read_thread.IsJoinable())
263 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
264 "%p Communication::StopReadThread ()", this);
266 m_read_thread_enabled = false;
268 BroadcastEvent (eBroadcastBitReadThreadShouldExit, NULL);
270 // error = m_read_thread.Cancel();
272 Error error = m_read_thread.Join(nullptr);
273 return error.Success();
277 Communication::JoinReadThread (Error *error_ptr)
279 if (!m_read_thread.IsJoinable())
282 Error error = m_read_thread.Join(nullptr);
283 return error.Success();
287 Communication::GetCachedBytes (void *dst, size_t dst_len)
289 Mutex::Locker locker(m_bytes_mutex);
290 if (m_bytes.size() > 0)
292 // If DST is NULL and we have a thread, then return the number
293 // of bytes that are available so the caller can call again
295 return m_bytes.size();
297 const size_t len = std::min<size_t>(dst_len, m_bytes.size());
299 ::memcpy (dst, m_bytes.c_str(), len);
300 m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len);
308 Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, ConnectionStatus status)
310 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
311 "%p Communication::AppendBytesToCache (src = %p, src_len = %" PRIu64 ", broadcast = %i)",
312 this, bytes, (uint64_t)len, broadcast);
313 if ((bytes == NULL || len == 0)
314 && (status != lldb::eConnectionStatusEndOfFile))
318 // If the user registered a callback, then call it and do not broadcast
319 m_callback (m_callback_baton, bytes, len);
321 else if (bytes != NULL && len > 0)
323 Mutex::Locker locker(m_bytes_mutex);
324 m_bytes.append ((const char *)bytes, len);
326 BroadcastEventIfUnique (eBroadcastBitReadThreadGotBytes);
331 Communication::ReadFromConnection (void *dst,
333 uint32_t timeout_usec,
334 ConnectionStatus &status,
337 lldb::ConnectionSP connection_sp (m_connection_sp);
338 if (connection_sp.get())
339 return connection_sp->Read (dst, dst_len, timeout_usec, status, error_ptr);
344 Communication::ReadThreadIsRunning ()
346 return m_read_thread_enabled;
349 lldb::thread_result_t
350 Communication::ReadThread (lldb::thread_arg_t p)
352 Communication *comm = (Communication *)p;
354 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
357 log->Printf ("%p Communication::ReadThread () thread starting...", p);
362 ConnectionStatus status = eConnectionStatusSuccess;
364 while (!done && comm->m_read_thread_enabled)
366 size_t bytes_read = comm->ReadFromConnection (buf, sizeof(buf), 5 * TimeValue::MicroSecPerSec, status, &error);
368 comm->AppendBytesToCache (buf, bytes_read, true, status);
369 else if ((bytes_read == 0)
370 && status == eConnectionStatusEndOfFile)
372 if (comm->GetCloseOnEOF ())
374 comm->AppendBytesToCache (buf, bytes_read, true, status);
379 case eConnectionStatusSuccess:
382 case eConnectionStatusEndOfFile:
385 case eConnectionStatusError: // Check GetError() for details
386 if (error.GetType() == eErrorTypePOSIX && error.GetError() == EIO)
388 // EIO on a pipe is usually caused by remote shutdown
393 error.LogIfError (log,
394 "%p Communication::ReadFromConnection () => status = %s",
396 Communication::ConnectionStatusAsCString (status));
398 case eConnectionStatusInterrupted: // Synchronization signal from SynchronizeWithReadThread()
399 // The connection returns eConnectionStatusInterrupted only when there is no
400 // input pending to be read, so we can signal that.
401 comm->BroadcastEvent (eBroadcastBitNoMorePendingInput);
403 case eConnectionStatusNoConnection: // No connection
404 case eConnectionStatusLostConnection: // Lost connection while connected to a valid connection
407 case eConnectionStatusTimedOut: // Request timed out
409 error.LogIfError (log,
410 "%p Communication::ReadFromConnection () => status = %s",
412 Communication::ConnectionStatusAsCString (status));
416 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION);
418 log->Printf ("%p Communication::ReadThread () thread exiting...", p);
420 comm->m_read_thread_did_exit = true;
421 // Let clients know that this thread is exiting
422 comm->BroadcastEvent (eBroadcastBitNoMorePendingInput);
423 comm->BroadcastEvent (eBroadcastBitReadThreadDidExit);
428 Communication::SetReadThreadBytesReceivedCallback
430 ReadThreadBytesReceived callback,
434 m_callback = callback;
435 m_callback_baton = callback_baton;
439 Communication::SynchronizeWithReadThread ()
441 // Only one thread can do the synchronization dance at a time.
442 Mutex::Locker locker(m_synchronize_mutex);
444 // First start listening for the synchronization event.
445 Listener listener("Communication::SyncronizeWithReadThread");
446 listener.StartListeningForEvents(this, eBroadcastBitNoMorePendingInput);
448 // If the thread is not running, there is no point in synchronizing.
449 if (!m_read_thread_enabled || m_read_thread_did_exit)
452 // Notify the read thread.
453 m_connection_sp->InterruptRead();
455 // Wait for the synchronization event.
457 listener.WaitForEvent(NULL, event_sp);
461 Communication::SetConnection (Connection *connection)
464 StopReadThread(NULL);
465 m_connection_sp.reset(connection);
469 Communication::ConnectionStatusAsCString (lldb::ConnectionStatus status)
473 case eConnectionStatusSuccess: return "success";
474 case eConnectionStatusError: return "error";
475 case eConnectionStatusTimedOut: return "timed out";
476 case eConnectionStatusNoConnection: return "no connection";
477 case eConnectionStatusLostConnection: return "lost connection";
478 case eConnectionStatusEndOfFile: return "end of file";
479 case eConnectionStatusInterrupted: return "interrupted";
482 static char unknown_state_string[64];
483 snprintf(unknown_state_string, sizeof (unknown_state_string), "ConnectionStatus = %i", status);
484 return unknown_state_string;