]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Core/Communication.cpp
Merging ^/head r279596 through r279758.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Core / Communication.cpp
1 //===-- Communication.cpp ---------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project 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"
23 #include <string.h>
24
25 using namespace lldb;
26 using namespace lldb_private;
27
28 ConstString &
29 Communication::GetStaticBroadcasterClass ()
30 {
31     static ConstString class_name ("lldb.communication");
32     return class_name;
33 }
34
35 //----------------------------------------------------------------------
36 // Constructor
37 //----------------------------------------------------------------------
38 Communication::Communication(const char *name) :
39     Broadcaster (NULL, name),
40     m_connection_sp (),
41     m_read_thread_enabled (false),
42     m_bytes(),
43     m_bytes_mutex (Mutex::eMutexTypeRecursive),
44     m_write_mutex (Mutex::eMutexTypeNormal),
45     m_callback (NULL),
46     m_callback_baton (NULL),
47     m_close_on_eof (true)
48
49 {
50     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
51                                  "%p Communication::Communication (name = %s)",
52                                  this, name);
53
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");
59     
60     CheckInWithManager();
61 }
62
63 //----------------------------------------------------------------------
64 // Destructor
65 //----------------------------------------------------------------------
66 Communication::~Communication()
67 {
68     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION,
69                                  "%p Communication::~Communication (name = %s)",
70                                  this, m_broadcaster_name.AsCString(""));
71     Clear();
72 }
73
74 void
75 Communication::Clear()
76 {
77     SetReadThreadBytesReceivedCallback (NULL, NULL);
78     Disconnect (NULL);
79     StopReadThread (NULL);
80 }
81
82 ConnectionStatus
83 Communication::Connect (const char *url, Error *error_ptr)
84 {
85     Clear();
86
87     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Connect (url = %s)", this, url);
88
89     lldb::ConnectionSP connection_sp (m_connection_sp);
90     if (connection_sp.get())
91         return connection_sp->Connect (url, error_ptr);
92     if (error_ptr)
93         error_ptr->SetErrorString("Invalid connection.");
94     return eConnectionStatusNoConnection;
95 }
96
97 ConnectionStatus
98 Communication::Disconnect (Error *error_ptr)
99 {
100     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Disconnect ()", this);
101
102     lldb::ConnectionSP connection_sp (m_connection_sp);
103     if (connection_sp.get())
104     {
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.
111         //
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
114         // upon disconnnect.
115         //connection_sp.reset();
116         return status;
117     }
118     return eConnectionStatusNoConnection;
119 }
120
121 bool
122 Communication::IsConnected () const
123 {
124     lldb::ConnectionSP connection_sp (m_connection_sp);
125     if (connection_sp.get())
126         return connection_sp->IsConnected ();
127     return false;
128 }
129
130 bool
131 Communication::HasConnection () const
132 {
133     return m_connection_sp.get() != NULL;
134 }
135
136 size_t
137 Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr)
138 {
139     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
140                                          "%p Communication::Read (dst = %p, dst_len = %" PRIu64 ", timeout = %u usec) connection = %p",
141                                          this, 
142                                          dst, 
143                                          (uint64_t)dst_len,
144                                          timeout_usec, 
145                                          m_connection_sp.get());
146
147     if (m_read_thread_enabled)
148     {
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)
152         {
153             status = eConnectionStatusSuccess;
154             return cached_bytes;
155         }
156
157         if (m_connection_sp.get() == NULL)
158         {
159             if (error_ptr)
160                 error_ptr->SetErrorString("Invalid connection.");
161             status = eConnectionStatusNoConnection;
162             return 0;
163         }
164         // Set the timeout appropriately
165         TimeValue timeout_time;
166         if (timeout_usec != UINT32_MAX)
167         {
168             timeout_time = TimeValue::Now();
169             timeout_time.OffsetWithMicroSeconds (timeout_usec);
170         }
171
172         Listener listener ("Communication::Read");
173         listener.StartListeningForEvents (this, eBroadcastBitReadThreadGotBytes | eBroadcastBitReadThreadDidExit);
174         EventSP event_sp;
175         while (listener.WaitForEvent (timeout_time.IsValid() ? &timeout_time : NULL, event_sp))
176         {
177             const uint32_t event_type = event_sp->GetType();
178             if (event_type & eBroadcastBitReadThreadGotBytes)
179             {
180                 return GetCachedBytes (dst, dst_len);
181             }
182
183             if (event_type & eBroadcastBitReadThreadDidExit)
184             {
185                 Disconnect (NULL);
186                 break;
187             }
188         }
189         return 0;
190     }
191
192     // We aren't using a read thread, just read the data synchronously in this
193     // thread.
194     lldb::ConnectionSP connection_sp (m_connection_sp);
195     if (connection_sp.get())
196     {
197         return connection_sp->Read (dst, dst_len, timeout_usec, status, error_ptr);
198     }
199
200     if (error_ptr)
201         error_ptr->SetErrorString("Invalid connection.");
202     status = eConnectionStatusNoConnection;
203     return 0;
204 }
205
206
207 size_t
208 Communication::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr)
209 {
210     lldb::ConnectionSP connection_sp (m_connection_sp);
211
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",
215                                          this, 
216                                          src, 
217                                          (uint64_t)src_len,
218                                          connection_sp.get());
219
220     if (connection_sp.get())
221         return connection_sp->Write (src, src_len, status, error_ptr);
222
223     if (error_ptr)
224         error_ptr->SetErrorString("Invalid connection.");
225     status = eConnectionStatusNoConnection;
226     return 0;
227 }
228
229
230 bool
231 Communication::StartReadThread (Error *error_ptr)
232 {
233     if (error_ptr)
234         error_ptr->Clear();
235
236     if (m_read_thread.IsJoinable())
237         return true;
238
239     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
240                                  "%p Communication::StartReadThread ()", this);
241
242
243     char thread_name[1024];
244     snprintf(thread_name, sizeof(thread_name), "<lldb.comm.%s>", m_broadcaster_name.AsCString());
245
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;
251 }
252
253 bool
254 Communication::StopReadThread (Error *error_ptr)
255 {
256     if (!m_read_thread.IsJoinable())
257         return true;
258
259     lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION,
260                                  "%p Communication::StopReadThread ()", this);
261
262     m_read_thread_enabled = false;
263
264     BroadcastEvent (eBroadcastBitReadThreadShouldExit, NULL);
265
266     // error = m_read_thread.Cancel();
267
268     Error error = m_read_thread.Join(nullptr);
269     return error.Success();
270 }
271
272 bool
273 Communication::JoinReadThread (Error *error_ptr)
274 {
275     if (!m_read_thread.IsJoinable())
276         return true;
277
278     Error error = m_read_thread.Join(nullptr);
279     return error.Success();
280 }
281
282 size_t
283 Communication::GetCachedBytes (void *dst, size_t dst_len)
284 {
285     Mutex::Locker locker(m_bytes_mutex);
286     if (m_bytes.size() > 0)
287     {
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
290         if (dst == NULL)
291             return m_bytes.size();
292
293         const size_t len = std::min<size_t>(dst_len, m_bytes.size());
294
295         ::memcpy (dst, m_bytes.c_str(), len);
296         m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len);
297
298         return len;
299     }
300     return 0;
301 }
302
303 void
304 Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, ConnectionStatus status)
305 {
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))
311         return;
312     if (m_callback)
313     {
314         // If the user registered a callback, then call it and do not broadcast
315         m_callback (m_callback_baton, bytes, len);
316     }
317     else if (bytes != NULL && len > 0)
318     {
319         Mutex::Locker locker(m_bytes_mutex);
320         m_bytes.append ((const char *)bytes, len);
321         if (broadcast)
322             BroadcastEventIfUnique (eBroadcastBitReadThreadGotBytes);
323     }
324 }
325
326 size_t
327 Communication::ReadFromConnection (void *dst, 
328                                    size_t dst_len, 
329                                    uint32_t timeout_usec,
330                                    ConnectionStatus &status, 
331                                    Error *error_ptr)
332 {
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);
336     return 0;
337 }
338
339 bool
340 Communication::ReadThreadIsRunning ()
341 {
342     return m_read_thread_enabled;
343 }
344
345 lldb::thread_result_t
346 Communication::ReadThread (lldb::thread_arg_t p)
347 {
348     Communication *comm = (Communication *)p;
349
350     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION));
351
352     if (log)
353         log->Printf ("%p Communication::ReadThread () thread starting...", p);
354
355     uint8_t buf[1024];
356
357     Error error;
358     ConnectionStatus status = eConnectionStatusSuccess;
359     bool done = false;
360     while (!done && comm->m_read_thread_enabled)
361     {
362         size_t bytes_read = comm->ReadFromConnection (buf, sizeof(buf), 5 * TimeValue::MicroSecPerSec, status, &error);
363         if (bytes_read > 0)
364             comm->AppendBytesToCache (buf, bytes_read, true, status);
365         else if ((bytes_read == 0)
366                 && status == eConnectionStatusEndOfFile)
367         {
368             if (comm->GetCloseOnEOF ())
369                 comm->Disconnect ();
370             comm->AppendBytesToCache (buf, bytes_read, true, status);
371         }
372
373         switch (status)
374         {
375         case eConnectionStatusSuccess:
376             break;
377
378         case eConnectionStatusEndOfFile:
379             if (comm->GetCloseOnEOF())
380                  done = true;
381              break;
382         case eConnectionStatusError:            // Check GetError() for details
383             if (error.GetType() == eErrorTypePOSIX && error.GetError() == EIO)
384             {
385                 // EIO on a pipe is usually caused by remote shutdown
386                 comm->Disconnect ();
387                 done = true;
388             }
389             if (log)
390                 error.LogIfError (log,
391                                   "%p Communication::ReadFromConnection () => status = %s",
392                                   p,
393                                   Communication::ConnectionStatusAsCString (status));
394             break;
395         case eConnectionStatusNoConnection:     // No connection
396         case eConnectionStatusLostConnection:   // Lost connection while connected to a valid connection
397         case eConnectionStatusInterrupted:      // Interrupted
398             done = true;
399             // Fall through...
400         case eConnectionStatusTimedOut:         // Request timed out
401             if (log)
402                 error.LogIfError (log,
403                                   "%p Communication::ReadFromConnection () => status = %s",
404                                   p,
405                                   Communication::ConnectionStatusAsCString (status));
406             break;
407         }
408     }
409     log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION);
410     if (log)
411         log->Printf ("%p Communication::ReadThread () thread exiting...", p);
412
413     // Let clients know that this thread is exiting
414     comm->BroadcastEvent (eBroadcastBitReadThreadDidExit);
415     return NULL;
416 }
417
418 void
419 Communication::SetReadThreadBytesReceivedCallback
420 (
421     ReadThreadBytesReceived callback,
422     void *callback_baton
423 )
424 {
425     m_callback = callback;
426     m_callback_baton = callback_baton;
427 }
428
429 void
430 Communication::SetConnection (Connection *connection)
431 {
432     Disconnect (NULL);
433     StopReadThread(NULL);
434     m_connection_sp.reset(connection);
435 }
436
437 const char *
438 Communication::ConnectionStatusAsCString (lldb::ConnectionStatus status)
439 {
440     switch (status)
441     {
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";
449     }
450
451     static char unknown_state_string[64];
452     snprintf(unknown_state_string, sizeof (unknown_state_string), "ConnectionStatus = %i", status);
453     return unknown_state_string;
454 }