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/lldb-private-log.h"
15 #include "lldb/Core/Communication.h"
16 #include "lldb/Core/Connection.h"
17 #include "lldb/Core/Log.h"
18 #include "lldb/Core/Timer.h"
19 #include "lldb/Core/Event.h"
20 #include "lldb/Host/Host.h"
21 #include "lldb/Host/HostThread.h"
22 #include "lldb/Host/ThreadLauncher.h"
26 using namespace lldb_private;
29 Communication::GetStaticBroadcasterClass ()
31 static ConstString class_name ("lldb.communication");
35 //----------------------------------------------------------------------
37 //----------------------------------------------------------------------
38 Communication::Communication(const char *name) :
39 Broadcaster (NULL, name),
41 m_read_thread_enabled (false),
43 m_bytes_mutex (Mutex::eMutexTypeRecursive),
44 m_write_mutex (Mutex::eMutexTypeNormal),
46 m_callback_baton (NULL),
50 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
51 "%p Communication::Communication (name = %s)",
54 SetEventName (eBroadcastBitDisconnected, "disconnected");
55 SetEventName (eBroadcastBitReadThreadGotBytes, "got bytes");
56 SetEventName (eBroadcastBitReadThreadDidExit, "read thread did exit");
57 SetEventName (eBroadcastBitReadThreadShouldExit, "read thread should exit");
58 SetEventName (eBroadcastBitPacketAvailable, "packet available");
63 //----------------------------------------------------------------------
65 //----------------------------------------------------------------------
66 Communication::~Communication()
68 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
69 "%p Communication::~Communication (name = %s)",
70 this, m_broadcaster_name.AsCString(""));
75 Communication::Clear()
77 SetReadThreadBytesReceivedCallback (NULL, NULL);
79 StopReadThread (NULL);
83 Communication::Connect (const char *url, Error *error_ptr)
87 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Connect (url = %s)", this, url);
89 lldb::ConnectionSP connection_sp (m_connection_sp);
90 if (connection_sp.get())
91 return connection_sp->Connect (url, error_ptr);
93 error_ptr->SetErrorString("Invalid connection.");
94 return eConnectionStatusNoConnection;
98 Communication::Disconnect (Error *error_ptr)
100 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Disconnect ()", this);
102 lldb::ConnectionSP connection_sp (m_connection_sp);
103 if (connection_sp.get())
105 ConnectionStatus status = connection_sp->Disconnect (error_ptr);
106 // We currently don't protect connection_sp with any mutex for
107 // multi-threaded environments. So lets not nuke our connection class
108 // without putting some multi-threaded protections in. We also probably
109 // don't want to pay for the overhead it might cause if every time we
110 // access the connection we have to take a lock.
112 // This unique pointer will cleanup after itself when this object goes away,
113 // so there is no need to currently have it destroy itself immediately
115 //connection_sp.reset();
118 return eConnectionStatusNoConnection;
122 Communication::IsConnected () const
124 lldb::ConnectionSP connection_sp (m_connection_sp);
125 if (connection_sp.get())
126 return connection_sp->IsConnected ();
131 Communication::HasConnection () const
133 return m_connection_sp.get() != NULL;
137 Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr)
139 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
140 "%p Communication::Read (dst = %p, dst_len = %" PRIu64 ", timeout = %u usec) connection = %p",
145 m_connection_sp.get());
147 if (m_read_thread_enabled)
149 // We have a dedicated read thread that is getting data for us
150 size_t cached_bytes = GetCachedBytes (dst, dst_len);
151 if (cached_bytes > 0 || timeout_usec == 0)
153 status = eConnectionStatusSuccess;
157 if (m_connection_sp.get() == NULL)
160 error_ptr->SetErrorString("Invalid connection.");
161 status = eConnectionStatusNoConnection;
164 // Set the timeout appropriately
165 TimeValue timeout_time;
166 if (timeout_usec != UINT32_MAX)
168 timeout_time = TimeValue::Now();
169 timeout_time.OffsetWithMicroSeconds (timeout_usec);
172 Listener listener ("Communication::Read");
173 listener.StartListeningForEvents (this, eBroadcastBitReadThreadGotBytes | eBroadcastBitReadThreadDidExit);
175 while (listener.WaitForEvent (timeout_time.IsValid() ? &timeout_time : NULL, event_sp))
177 const uint32_t event_type = event_sp->GetType();
178 if (event_type & eBroadcastBitReadThreadGotBytes)
180 return GetCachedBytes (dst, dst_len);
183 if (event_type & eBroadcastBitReadThreadDidExit)
192 // We aren't using a read thread, just read the data synchronously in this
194 lldb::ConnectionSP connection_sp (m_connection_sp);
195 if (connection_sp.get())
197 return connection_sp->Read (dst, dst_len, timeout_usec, status, error_ptr);
201 error_ptr->SetErrorString("Invalid connection.");
202 status = eConnectionStatusNoConnection;
208 Communication::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr)
210 lldb::ConnectionSP connection_sp (m_connection_sp);
212 Mutex::Locker locker(m_write_mutex);
213 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
214 "%p Communication::Write (src = %p, src_len = %" PRIu64 ") connection = %p",
218 connection_sp.get());
220 if (connection_sp.get())
221 return connection_sp->Write (src, src_len, status, error_ptr);
224 error_ptr->SetErrorString("Invalid connection.");
225 status = eConnectionStatusNoConnection;
231 Communication::StartReadThread (Error *error_ptr)
236 if (m_read_thread.IsJoinable())
239 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
240 "%p Communication::StartReadThread ()", this);
243 char thread_name[1024];
244 snprintf(thread_name, sizeof(thread_name), "<lldb.comm.%s>", m_broadcaster_name.AsCString());
246 m_read_thread_enabled = true;
247 m_read_thread = ThreadLauncher::LaunchThread(thread_name, Communication::ReadThread, this, error_ptr);
248 if (!m_read_thread.IsJoinable())
249 m_read_thread_enabled = false;
250 return m_read_thread_enabled;
254 Communication::StopReadThread (Error *error_ptr)
256 if (!m_read_thread.IsJoinable())
259 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
260 "%p Communication::StopReadThread ()", this);
262 m_read_thread_enabled = false;
264 BroadcastEvent (eBroadcastBitReadThreadShouldExit, NULL);
266 // error = m_read_thread.Cancel();
268 Error error = m_read_thread.Join(nullptr);
269 return error.Success();
273 Communication::JoinReadThread (Error *error_ptr)
275 if (!m_read_thread.IsJoinable())
278 Error error = m_read_thread.Join(nullptr);
279 return error.Success();
283 Communication::GetCachedBytes (void *dst, size_t dst_len)
285 Mutex::Locker locker(m_bytes_mutex);
286 if (m_bytes.size() > 0)
288 // If DST is NULL and we have a thread, then return the number
289 // of bytes that are available so the caller can call again
291 return m_bytes.size();
293 const size_t len = std::min<size_t>(dst_len, m_bytes.size());
295 ::memcpy (dst, m_bytes.c_str(), len);
296 m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len);
304 Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, ConnectionStatus status)
306 lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
307 "%p Communication::AppendBytesToCache (src = %p, src_len = %" PRIu64 ", broadcast = %i)",
308 this, bytes, (uint64_t)len, broadcast);
309 if ((bytes == NULL || len == 0)
310 && (status != lldb::eConnectionStatusEndOfFile))
314 // If the user registered a callback, then call it and do not broadcast
315 m_callback (m_callback_baton, bytes, len);
317 else if (bytes != NULL && len > 0)
319 Mutex::Locker locker(m_bytes_mutex);
320 m_bytes.append ((const char *)bytes, len);
322 BroadcastEventIfUnique (eBroadcastBitReadThreadGotBytes);
327 Communication::ReadFromConnection (void *dst,
329 uint32_t timeout_usec,
330 ConnectionStatus &status,
333 lldb::ConnectionSP connection_sp (m_connection_sp);
334 if (connection_sp.get())
335 return connection_sp->Read (dst, dst_len, timeout_usec, status, error_ptr);
340 Communication::ReadThreadIsRunning ()
342 return m_read_thread_enabled;
345 lldb::thread_result_t
346 Communication::ReadThread (lldb::thread_arg_t p)
348 Communication *comm = (Communication *)p;
350 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
353 log->Printf ("%p Communication::ReadThread () thread starting...", p);
358 ConnectionStatus status = eConnectionStatusSuccess;
360 while (!done && comm->m_read_thread_enabled)
362 size_t bytes_read = comm->ReadFromConnection (buf, sizeof(buf), 5 * TimeValue::MicroSecPerSec, status, &error);
364 comm->AppendBytesToCache (buf, bytes_read, true, status);
365 else if ((bytes_read == 0)
366 && status == eConnectionStatusEndOfFile)
368 if (comm->GetCloseOnEOF ())
370 comm->AppendBytesToCache (buf, bytes_read, true, status);
375 case eConnectionStatusSuccess:
378 case eConnectionStatusEndOfFile:
379 if (comm->GetCloseOnEOF())
382 case eConnectionStatusError: // Check GetError() for details
383 if (error.GetType() == eErrorTypePOSIX && error.GetError() == EIO)
385 // EIO on a pipe is usually caused by remote shutdown
390 error.LogIfError (log,
391 "%p Communication::ReadFromConnection () => status = %s",
393 Communication::ConnectionStatusAsCString (status));
395 case eConnectionStatusNoConnection: // No connection
396 case eConnectionStatusLostConnection: // Lost connection while connected to a valid connection
397 case eConnectionStatusInterrupted: // Interrupted
400 case eConnectionStatusTimedOut: // Request timed out
402 error.LogIfError (log,
403 "%p Communication::ReadFromConnection () => status = %s",
405 Communication::ConnectionStatusAsCString (status));
409 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION);
411 log->Printf ("%p Communication::ReadThread () thread exiting...", p);
413 // Let clients know that this thread is exiting
414 comm->BroadcastEvent (eBroadcastBitReadThreadDidExit);
419 Communication::SetReadThreadBytesReceivedCallback
421 ReadThreadBytesReceived callback,
425 m_callback = callback;
426 m_callback_baton = callback_baton;
430 Communication::SetConnection (Connection *connection)
433 StopReadThread(NULL);
434 m_connection_sp.reset(connection);
438 Communication::ConnectionStatusAsCString (lldb::ConnectionStatus status)
442 case eConnectionStatusSuccess: return "success";
443 case eConnectionStatusError: return "error";
444 case eConnectionStatusTimedOut: return "timed out";
445 case eConnectionStatusNoConnection: return "no connection";
446 case eConnectionStatusLostConnection: return "lost connection";
447 case eConnectionStatusEndOfFile: return "end of file";
448 case eConnectionStatusInterrupted: return "interrupted";
451 static char unknown_state_string[64];
452 snprintf(unknown_state_string, sizeof (unknown_state_string), "ConnectionStatus = %i", status);
453 return unknown_state_string;