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 } 455