1 //===-- ConnectionFileDescriptorPosix.cpp ---------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #if defined(__APPLE__) 10 // Enable this special support for Apple builds where we can have unlimited 11 // select bounds. We tried switching to poll() and kqueue and we were panicing 12 // the kernel, so we have to stick with select for now. 13 #define _DARWIN_UNLIMITED_SELECT 14 #endif 15 16 #include "lldb/Host/posix/ConnectionFileDescriptorPosix.h" 17 #include "lldb/Host/Config.h" 18 #include "lldb/Host/Socket.h" 19 #include "lldb/Host/SocketAddress.h" 20 #include "lldb/Utility/SelectHelper.h" 21 #include "lldb/Utility/Timeout.h" 22 23 #include <cerrno> 24 #include <cstdlib> 25 #include <cstring> 26 #include <fcntl.h> 27 #include <sys/types.h> 28 29 #if LLDB_ENABLE_POSIX 30 #include <termios.h> 31 #include <unistd.h> 32 #endif 33 34 #include <memory> 35 #include <sstream> 36 37 #include "llvm/Support/Errno.h" 38 #include "llvm/Support/ErrorHandling.h" 39 #if defined(__APPLE__) 40 #include "llvm/ADT/SmallVector.h" 41 #endif 42 #include "lldb/Host/Host.h" 43 #include "lldb/Host/Socket.h" 44 #include "lldb/Host/common/TCPSocket.h" 45 #include "lldb/Host/common/UDPSocket.h" 46 #include "lldb/Utility/Log.h" 47 #include "lldb/Utility/StreamString.h" 48 #include "lldb/Utility/Timer.h" 49 50 using namespace lldb; 51 using namespace lldb_private; 52 53 ConnectionFileDescriptor::ConnectionFileDescriptor(bool child_processes_inherit) 54 : Connection(), m_pipe(), m_mutex(), m_shutting_down(false), 55 56 m_child_processes_inherit(child_processes_inherit) { 57 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | 58 LIBLLDB_LOG_OBJECT)); 59 LLDB_LOGF(log, "%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", 60 static_cast<void *>(this)); 61 } 62 63 ConnectionFileDescriptor::ConnectionFileDescriptor(int fd, bool owns_fd) 64 : Connection(), m_pipe(), m_mutex(), m_shutting_down(false), 65 m_waiting_for_accept(false), m_child_processes_inherit(false) { 66 m_io_sp = 67 std::make_shared<NativeFile>(fd, File::eOpenOptionReadWrite, owns_fd); 68 69 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | 70 LIBLLDB_LOG_OBJECT)); 71 LLDB_LOGF(log, 72 "%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = " 73 "%i, owns_fd = %i)", 74 static_cast<void *>(this), fd, owns_fd); 75 OpenCommandPipe(); 76 } 77 78 ConnectionFileDescriptor::ConnectionFileDescriptor(Socket *socket) 79 : Connection(), m_pipe(), m_mutex(), m_shutting_down(false), 80 m_waiting_for_accept(false), m_child_processes_inherit(false) { 81 InitializeSocket(socket); 82 } 83 84 ConnectionFileDescriptor::~ConnectionFileDescriptor() { 85 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | 86 LIBLLDB_LOG_OBJECT)); 87 LLDB_LOGF(log, "%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", 88 static_cast<void *>(this)); 89 Disconnect(nullptr); 90 CloseCommandPipe(); 91 } 92 93 void ConnectionFileDescriptor::OpenCommandPipe() { 94 CloseCommandPipe(); 95 96 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 97 // Make the command file descriptor here: 98 Status result = m_pipe.CreateNew(m_child_processes_inherit); 99 if (!result.Success()) { 100 LLDB_LOGF(log, 101 "%p ConnectionFileDescriptor::OpenCommandPipe () - could not " 102 "make pipe: %s", 103 static_cast<void *>(this), result.AsCString()); 104 } else { 105 LLDB_LOGF(log, 106 "%p ConnectionFileDescriptor::OpenCommandPipe() - success " 107 "readfd=%d writefd=%d", 108 static_cast<void *>(this), m_pipe.GetReadFileDescriptor(), 109 m_pipe.GetWriteFileDescriptor()); 110 } 111 } 112 113 void ConnectionFileDescriptor::CloseCommandPipe() { 114 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 115 LLDB_LOGF(log, "%p ConnectionFileDescriptor::CloseCommandPipe()", 116 static_cast<void *>(this)); 117 118 m_pipe.Close(); 119 } 120 121 bool ConnectionFileDescriptor::IsConnected() const { 122 return m_io_sp && m_io_sp->IsValid(); 123 } 124 125 ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path, 126 Status *error_ptr) { 127 std::lock_guard<std::recursive_mutex> guard(m_mutex); 128 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 129 LLDB_LOGF(log, "%p ConnectionFileDescriptor::Connect (url = '%s')", 130 static_cast<void *>(this), path.str().c_str()); 131 132 OpenCommandPipe(); 133 134 if (path.empty()) { 135 if (error_ptr) 136 error_ptr->SetErrorString("invalid connect arguments"); 137 return eConnectionStatusError; 138 } 139 140 llvm::StringRef scheme; 141 std::tie(scheme, path) = path.split("://"); 142 143 if (!path.empty()) { 144 auto method = 145 llvm::StringSwitch<ConnectionStatus (ConnectionFileDescriptor::*)( 146 llvm::StringRef, Status *)>(scheme) 147 .Case("listen", &ConnectionFileDescriptor::SocketListenAndAccept) 148 .Cases("accept", "unix-accept", 149 &ConnectionFileDescriptor::NamedSocketAccept) 150 .Cases("connect", "tcp-connect", 151 &ConnectionFileDescriptor::ConnectTCP) 152 .Case("udp", &ConnectionFileDescriptor::ConnectUDP) 153 .Case("unix-connect", &ConnectionFileDescriptor::NamedSocketConnect) 154 .Case("unix-abstract-connect", 155 &ConnectionFileDescriptor::UnixAbstractSocketConnect) 156 #if LLDB_ENABLE_POSIX 157 .Case("fd", &ConnectionFileDescriptor::ConnectFD) 158 .Case("file", &ConnectionFileDescriptor::ConnectFile) 159 #endif 160 .Default(nullptr); 161 162 if (method) 163 return (this->*method)(path, error_ptr); 164 } 165 166 if (error_ptr) 167 error_ptr->SetErrorStringWithFormat("unsupported connection URL: '%s'", 168 path.str().c_str()); 169 return eConnectionStatusError; 170 } 171 172 bool ConnectionFileDescriptor::InterruptRead() { 173 size_t bytes_written = 0; 174 Status result = m_pipe.Write("i", 1, bytes_written); 175 return result.Success(); 176 } 177 178 ConnectionStatus ConnectionFileDescriptor::Disconnect(Status *error_ptr) { 179 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 180 LLDB_LOGF(log, "%p ConnectionFileDescriptor::Disconnect ()", 181 static_cast<void *>(this)); 182 183 ConnectionStatus status = eConnectionStatusSuccess; 184 185 if (!IsConnected()) { 186 LLDB_LOGF( 187 log, "%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect", 188 static_cast<void *>(this)); 189 return eConnectionStatusSuccess; 190 } 191 192 if (m_io_sp->GetFdType() == IOObject::eFDTypeSocket) 193 static_cast<Socket &>(*m_io_sp).PreDisconnect(); 194 195 // Try to get the ConnectionFileDescriptor's mutex. If we fail, that is 196 // quite likely because somebody is doing a blocking read on our file 197 // descriptor. If that's the case, then send the "q" char to the command 198 // file channel so the read will wake up and the connection will then know to 199 // shut down. 200 std::unique_lock<std::recursive_mutex> locker(m_mutex, std::defer_lock); 201 if (!locker.try_lock()) { 202 if (m_pipe.CanWrite()) { 203 size_t bytes_written = 0; 204 Status result = m_pipe.Write("q", 1, bytes_written); 205 LLDB_LOGF(log, 206 "%p ConnectionFileDescriptor::Disconnect(): Couldn't get " 207 "the lock, sent 'q' to %d, error = '%s'.", 208 static_cast<void *>(this), m_pipe.GetWriteFileDescriptor(), 209 result.AsCString()); 210 } else if (log) { 211 LLDB_LOGF(log, 212 "%p ConnectionFileDescriptor::Disconnect(): Couldn't get the " 213 "lock, but no command pipe is available.", 214 static_cast<void *>(this)); 215 } 216 locker.lock(); 217 } 218 219 // Prevents reads and writes during shutdown. 220 m_shutting_down = true; 221 222 Status error = m_io_sp->Close(); 223 if (error.Fail()) 224 status = eConnectionStatusError; 225 if (error_ptr) 226 *error_ptr = error; 227 228 // Close any pipes we were using for async interrupts 229 m_pipe.Close(); 230 231 m_uri.clear(); 232 m_shutting_down = false; 233 return status; 234 } 235 236 size_t ConnectionFileDescriptor::Read(void *dst, size_t dst_len, 237 const Timeout<std::micro> &timeout, 238 ConnectionStatus &status, 239 Status *error_ptr) { 240 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 241 242 std::unique_lock<std::recursive_mutex> locker(m_mutex, std::defer_lock); 243 if (!locker.try_lock()) { 244 LLDB_LOGF(log, 245 "%p ConnectionFileDescriptor::Read () failed to get the " 246 "connection lock.", 247 static_cast<void *>(this)); 248 if (error_ptr) 249 error_ptr->SetErrorString("failed to get the connection lock for read."); 250 251 status = eConnectionStatusTimedOut; 252 return 0; 253 } 254 255 if (m_shutting_down) { 256 if (error_ptr) 257 error_ptr->SetErrorString("shutting down"); 258 status = eConnectionStatusError; 259 return 0; 260 } 261 262 status = BytesAvailable(timeout, error_ptr); 263 if (status != eConnectionStatusSuccess) 264 return 0; 265 266 Status error; 267 size_t bytes_read = dst_len; 268 error = m_io_sp->Read(dst, bytes_read); 269 270 if (log) { 271 LLDB_LOGF(log, 272 "%p ConnectionFileDescriptor::Read() fd = %" PRIu64 273 ", dst = %p, dst_len = %" PRIu64 ") => %" PRIu64 ", error = %s", 274 static_cast<void *>(this), 275 static_cast<uint64_t>(m_io_sp->GetWaitableHandle()), 276 static_cast<void *>(dst), static_cast<uint64_t>(dst_len), 277 static_cast<uint64_t>(bytes_read), error.AsCString()); 278 } 279 280 if (bytes_read == 0) { 281 error.Clear(); // End-of-file. Do not automatically close; pass along for 282 // the end-of-file handlers. 283 status = eConnectionStatusEndOfFile; 284 } 285 286 if (error_ptr) 287 *error_ptr = error; 288 289 if (error.Fail()) { 290 uint32_t error_value = error.GetError(); 291 switch (error_value) { 292 case EAGAIN: // The file was marked for non-blocking I/O, and no data were 293 // ready to be read. 294 if (m_io_sp->GetFdType() == IOObject::eFDTypeSocket) 295 status = eConnectionStatusTimedOut; 296 else 297 status = eConnectionStatusSuccess; 298 return 0; 299 300 case EFAULT: // Buf points outside the allocated address space. 301 case EINTR: // A read from a slow device was interrupted before any data 302 // arrived by the delivery of a signal. 303 case EINVAL: // The pointer associated with fildes was negative. 304 case EIO: // An I/O error occurred while reading from the file system. 305 // The process group is orphaned. 306 // The file is a regular file, nbyte is greater than 0, the 307 // starting position is before the end-of-file, and the 308 // starting position is greater than or equal to the offset 309 // maximum established for the open file descriptor 310 // associated with fildes. 311 case EISDIR: // An attempt is made to read a directory. 312 case ENOBUFS: // An attempt to allocate a memory buffer fails. 313 case ENOMEM: // Insufficient memory is available. 314 status = eConnectionStatusError; 315 break; // Break to close.... 316 317 case ENOENT: // no such file or directory 318 case EBADF: // fildes is not a valid file or socket descriptor open for 319 // reading. 320 case ENXIO: // An action is requested of a device that does not exist.. 321 // A requested action cannot be performed by the device. 322 case ECONNRESET: // The connection is closed by the peer during a read 323 // attempt on a socket. 324 case ENOTCONN: // A read is attempted on an unconnected socket. 325 status = eConnectionStatusLostConnection; 326 break; // Break to close.... 327 328 case ETIMEDOUT: // A transmission timeout occurs during a read attempt on a 329 // socket. 330 status = eConnectionStatusTimedOut; 331 return 0; 332 333 default: 334 LLDB_LOG(log, "this = {0}, unexpected error: {1}", this, 335 llvm::sys::StrError(error_value)); 336 status = eConnectionStatusError; 337 break; // Break to close.... 338 } 339 340 return 0; 341 } 342 return bytes_read; 343 } 344 345 size_t ConnectionFileDescriptor::Write(const void *src, size_t src_len, 346 ConnectionStatus &status, 347 Status *error_ptr) { 348 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 349 LLDB_LOGF(log, 350 "%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64 351 ")", 352 static_cast<void *>(this), static_cast<const void *>(src), 353 static_cast<uint64_t>(src_len)); 354 355 if (!IsConnected()) { 356 if (error_ptr) 357 error_ptr->SetErrorString("not connected"); 358 status = eConnectionStatusNoConnection; 359 return 0; 360 } 361 362 if (m_shutting_down) { 363 if (error_ptr) 364 error_ptr->SetErrorString("shutting down"); 365 status = eConnectionStatusError; 366 return 0; 367 } 368 369 Status error; 370 371 size_t bytes_sent = src_len; 372 error = m_io_sp->Write(src, bytes_sent); 373 374 if (log) { 375 LLDB_LOGF(log, 376 "%p ConnectionFileDescriptor::Write(fd = %" PRIu64 377 ", src = %p, src_len = %" PRIu64 ") => %" PRIu64 " (error = %s)", 378 static_cast<void *>(this), 379 static_cast<uint64_t>(m_io_sp->GetWaitableHandle()), 380 static_cast<const void *>(src), static_cast<uint64_t>(src_len), 381 static_cast<uint64_t>(bytes_sent), error.AsCString()); 382 } 383 384 if (error_ptr) 385 *error_ptr = error; 386 387 if (error.Fail()) { 388 switch (error.GetError()) { 389 case EAGAIN: 390 case EINTR: 391 status = eConnectionStatusSuccess; 392 return 0; 393 394 case ECONNRESET: // The connection is closed by the peer during a read 395 // attempt on a socket. 396 case ENOTCONN: // A read is attempted on an unconnected socket. 397 status = eConnectionStatusLostConnection; 398 break; // Break to close.... 399 400 default: 401 status = eConnectionStatusError; 402 break; // Break to close.... 403 } 404 405 return 0; 406 } 407 408 status = eConnectionStatusSuccess; 409 return bytes_sent; 410 } 411 412 std::string ConnectionFileDescriptor::GetURI() { return m_uri; } 413 414 // This ConnectionFileDescriptor::BytesAvailable() uses select() via 415 // SelectHelper 416 // 417 // PROS: 418 // - select is consistent across most unix platforms 419 // - The Apple specific version allows for unlimited fds in the fd_sets by 420 // setting the _DARWIN_UNLIMITED_SELECT define prior to including the 421 // required header files. 422 // CONS: 423 // - on non-Apple platforms, only supports file descriptors up to FD_SETSIZE. 424 // This implementation will assert if it runs into that hard limit to let 425 // users know that another ConnectionFileDescriptor::BytesAvailable() should 426 // be used or a new version of ConnectionFileDescriptor::BytesAvailable() 427 // should be written for the system that is running into the limitations. 428 429 ConnectionStatus 430 ConnectionFileDescriptor::BytesAvailable(const Timeout<std::micro> &timeout, 431 Status *error_ptr) { 432 // Don't need to take the mutex here separately since we are only called from 433 // Read. If we ever get used more generally we will need to lock here as 434 // well. 435 436 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_CONNECTION)); 437 LLDB_LOG(log, "this = {0}, timeout = {1}", this, timeout); 438 439 // Make a copy of the file descriptors to make sure we don't have another 440 // thread change these values out from under us and cause problems in the 441 // loop below where like in FS_SET() 442 const IOObject::WaitableHandle handle = m_io_sp->GetWaitableHandle(); 443 const int pipe_fd = m_pipe.GetReadFileDescriptor(); 444 445 if (handle != IOObject::kInvalidHandleValue) { 446 SelectHelper select_helper; 447 if (timeout) 448 select_helper.SetTimeout(*timeout); 449 450 select_helper.FDSetRead(handle); 451 #if defined(_WIN32) 452 // select() won't accept pipes on Windows. The entire Windows codepath 453 // needs to be converted over to using WaitForMultipleObjects and event 454 // HANDLEs, but for now at least this will allow ::select() to not return 455 // an error. 456 const bool have_pipe_fd = false; 457 #else 458 const bool have_pipe_fd = pipe_fd >= 0; 459 #endif 460 if (have_pipe_fd) 461 select_helper.FDSetRead(pipe_fd); 462 463 while (handle == m_io_sp->GetWaitableHandle()) { 464 465 Status error = select_helper.Select(); 466 467 if (error_ptr) 468 *error_ptr = error; 469 470 if (error.Fail()) { 471 switch (error.GetError()) { 472 case EBADF: // One of the descriptor sets specified an invalid 473 // descriptor. 474 return eConnectionStatusLostConnection; 475 476 case EINVAL: // The specified time limit is invalid. One of its 477 // components is negative or too large. 478 default: // Other unknown error 479 return eConnectionStatusError; 480 481 case ETIMEDOUT: 482 return eConnectionStatusTimedOut; 483 484 case EAGAIN: // The kernel was (perhaps temporarily) unable to 485 // allocate the requested number of file descriptors, or 486 // we have non-blocking IO 487 case EINTR: // A signal was delivered before the time limit 488 // expired and before any of the selected events occurred. 489 break; // Lets keep reading to until we timeout 490 } 491 } else { 492 if (select_helper.FDIsSetRead(handle)) 493 return eConnectionStatusSuccess; 494 495 if (select_helper.FDIsSetRead(pipe_fd)) { 496 // There is an interrupt or exit command in the command pipe Read the 497 // data from that pipe: 498 char c; 499 500 ssize_t bytes_read = llvm::sys::RetryAfterSignal(-1, ::read, pipe_fd, &c, 1); 501 assert(bytes_read == 1); 502 (void)bytes_read; 503 switch (c) { 504 case 'q': 505 LLDB_LOGF(log, 506 "%p ConnectionFileDescriptor::BytesAvailable() " 507 "got data: %c from the command channel.", 508 static_cast<void *>(this), c); 509 return eConnectionStatusEndOfFile; 510 case 'i': 511 // Interrupt the current read 512 return eConnectionStatusInterrupted; 513 } 514 } 515 } 516 } 517 } 518 519 if (error_ptr) 520 error_ptr->SetErrorString("not connected"); 521 return eConnectionStatusLostConnection; 522 } 523 524 ConnectionStatus 525 ConnectionFileDescriptor::NamedSocketAccept(llvm::StringRef socket_name, 526 Status *error_ptr) { 527 Socket *socket = nullptr; 528 Status error = 529 Socket::UnixDomainAccept(socket_name, m_child_processes_inherit, socket); 530 if (error_ptr) 531 *error_ptr = error; 532 m_io_sp.reset(socket); 533 if (error.Fail()) 534 return eConnectionStatusError; 535 m_uri.assign(std::string(socket_name)); 536 return eConnectionStatusSuccess; 537 } 538 539 ConnectionStatus 540 ConnectionFileDescriptor::NamedSocketConnect(llvm::StringRef socket_name, 541 Status *error_ptr) { 542 Socket *socket = nullptr; 543 Status error = 544 Socket::UnixDomainConnect(socket_name, m_child_processes_inherit, socket); 545 if (error_ptr) 546 *error_ptr = error; 547 m_io_sp.reset(socket); 548 if (error.Fail()) 549 return eConnectionStatusError; 550 m_uri.assign(std::string(socket_name)); 551 return eConnectionStatusSuccess; 552 } 553 554 lldb::ConnectionStatus 555 ConnectionFileDescriptor::UnixAbstractSocketConnect(llvm::StringRef socket_name, 556 Status *error_ptr) { 557 Socket *socket = nullptr; 558 Status error = Socket::UnixAbstractConnect(socket_name, 559 m_child_processes_inherit, socket); 560 if (error_ptr) 561 *error_ptr = error; 562 m_io_sp.reset(socket); 563 if (error.Fail()) 564 return eConnectionStatusError; 565 m_uri.assign(std::string(socket_name)); 566 return eConnectionStatusSuccess; 567 } 568 569 ConnectionStatus 570 ConnectionFileDescriptor::SocketListenAndAccept(llvm::StringRef s, 571 Status *error_ptr) { 572 if (error_ptr) 573 *error_ptr = Status(); 574 m_port_predicate.SetValue(0, eBroadcastNever); 575 576 m_waiting_for_accept = true; 577 llvm::Expected<std::unique_ptr<TCPSocket>> listening_socket = 578 Socket::TcpListen(s, m_child_processes_inherit, &m_port_predicate); 579 if (!listening_socket) { 580 if (error_ptr) 581 *error_ptr = listening_socket.takeError(); 582 else 583 LLDB_LOG_ERROR(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION), 584 listening_socket.takeError(), "tcp listen failed: {0}"); 585 return eConnectionStatusError; 586 } 587 588 589 Socket *accepted_socket; 590 Status error = listening_socket.get()->Accept(accepted_socket); 591 if (error_ptr) 592 *error_ptr = error; 593 if (error.Fail()) 594 return eConnectionStatusError; 595 596 InitializeSocket(accepted_socket); 597 return eConnectionStatusSuccess; 598 } 599 600 ConnectionStatus ConnectionFileDescriptor::ConnectTCP(llvm::StringRef s, 601 Status *error_ptr) { 602 if (error_ptr) 603 *error_ptr = Status(); 604 605 llvm::Expected<std::unique_ptr<Socket>> socket = 606 Socket::TcpConnect(s, m_child_processes_inherit); 607 if (!socket) { 608 if (error_ptr) 609 *error_ptr = socket.takeError(); 610 else 611 LLDB_LOG_ERROR(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION), 612 socket.takeError(), "tcp connect failed: {0}"); 613 return eConnectionStatusError; 614 } 615 m_io_sp = std::move(*socket); 616 m_uri.assign(std::string(s)); 617 return eConnectionStatusSuccess; 618 } 619 620 ConnectionStatus ConnectionFileDescriptor::ConnectUDP(llvm::StringRef s, 621 Status *error_ptr) { 622 if (error_ptr) 623 *error_ptr = Status(); 624 llvm::Expected<std::unique_ptr<UDPSocket>> socket = 625 Socket::UdpConnect(s, m_child_processes_inherit); 626 if (!socket) { 627 if (error_ptr) 628 *error_ptr = socket.takeError(); 629 else 630 LLDB_LOG_ERROR(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION), 631 socket.takeError(), "tcp connect failed: {0}"); 632 return eConnectionStatusError; 633 } 634 m_io_sp = std::move(*socket); 635 m_uri.assign(std::string(s)); 636 return eConnectionStatusSuccess; 637 } 638 639 ConnectionStatus ConnectionFileDescriptor::ConnectFD(llvm::StringRef s, 640 Status *error_ptr) { 641 #if LLDB_ENABLE_POSIX 642 // Just passing a native file descriptor within this current process that 643 // is already opened (possibly from a service or other source). 644 int fd = -1; 645 646 if (!s.getAsInteger(0, fd)) { 647 // We have what looks to be a valid file descriptor, but we should make 648 // sure it is. We currently are doing this by trying to get the flags 649 // from the file descriptor and making sure it isn't a bad fd. 650 errno = 0; 651 int flags = ::fcntl(fd, F_GETFL, 0); 652 if (flags == -1 || errno == EBADF) { 653 if (error_ptr) 654 error_ptr->SetErrorStringWithFormat("stale file descriptor: %s", 655 s.str().c_str()); 656 m_io_sp.reset(); 657 return eConnectionStatusError; 658 } else { 659 // Don't take ownership of a file descriptor that gets passed to us 660 // since someone else opened the file descriptor and handed it to us. 661 // TODO: Since are using a URL to open connection we should 662 // eventually parse options using the web standard where we have 663 // "fd://123?opt1=value;opt2=value" and we can have an option be 664 // "owns=1" or "owns=0" or something like this to allow us to specify 665 // this. For now, we assume we must assume we don't own it. 666 667 std::unique_ptr<TCPSocket> tcp_socket; 668 tcp_socket = std::make_unique<TCPSocket>(fd, false, false); 669 // Try and get a socket option from this file descriptor to see if 670 // this is a socket and set m_is_socket accordingly. 671 int resuse; 672 bool is_socket = 673 !!tcp_socket->GetOption(SOL_SOCKET, SO_REUSEADDR, resuse); 674 if (is_socket) 675 m_io_sp = std::move(tcp_socket); 676 else 677 m_io_sp = 678 std::make_shared<NativeFile>(fd, File::eOpenOptionReadWrite, false); 679 m_uri = s.str(); 680 return eConnectionStatusSuccess; 681 } 682 } 683 684 if (error_ptr) 685 error_ptr->SetErrorStringWithFormat("invalid file descriptor: \"%s\"", 686 s.str().c_str()); 687 m_io_sp.reset(); 688 return eConnectionStatusError; 689 #endif // LLDB_ENABLE_POSIX 690 llvm_unreachable("this function should be only called w/ LLDB_ENABLE_POSIX"); 691 } 692 693 ConnectionStatus ConnectionFileDescriptor::ConnectFile(llvm::StringRef s, 694 Status *error_ptr) { 695 #if LLDB_ENABLE_POSIX 696 std::string addr_str = s.str(); 697 // file:///PATH 698 int fd = llvm::sys::RetryAfterSignal(-1, ::open, addr_str.c_str(), O_RDWR); 699 if (fd == -1) { 700 if (error_ptr) 701 error_ptr->SetErrorToErrno(); 702 return eConnectionStatusError; 703 } 704 705 if (::isatty(fd)) { 706 // Set up serial terminal emulation 707 struct termios options; 708 ::tcgetattr(fd, &options); 709 710 // Set port speed to maximum 711 ::cfsetospeed(&options, B115200); 712 ::cfsetispeed(&options, B115200); 713 714 // Raw input, disable echo and signals 715 options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 716 717 // Make sure only one character is needed to return from a read 718 options.c_cc[VMIN] = 1; 719 options.c_cc[VTIME] = 0; 720 721 llvm::sys::RetryAfterSignal(-1, ::tcsetattr, fd, TCSANOW, &options); 722 } 723 724 int flags = ::fcntl(fd, F_GETFL, 0); 725 if (flags >= 0) { 726 if ((flags & O_NONBLOCK) == 0) { 727 flags |= O_NONBLOCK; 728 ::fcntl(fd, F_SETFL, flags); 729 } 730 } 731 m_io_sp = 732 std::make_shared<NativeFile>(fd, File::eOpenOptionReadWrite, true); 733 return eConnectionStatusSuccess; 734 #endif // LLDB_ENABLE_POSIX 735 llvm_unreachable("this function should be only called w/ LLDB_ENABLE_POSIX"); 736 } 737 738 uint16_t 739 ConnectionFileDescriptor::GetListeningPort(const Timeout<std::micro> &timeout) { 740 auto Result = m_port_predicate.WaitForValueNotEqualTo(0, timeout); 741 return Result ? *Result : 0; 742 } 743 744 bool ConnectionFileDescriptor::GetChildProcessesInherit() const { 745 return m_child_processes_inherit; 746 } 747 748 void ConnectionFileDescriptor::SetChildProcessesInherit( 749 bool child_processes_inherit) { 750 m_child_processes_inherit = child_processes_inherit; 751 } 752 753 void ConnectionFileDescriptor::InitializeSocket(Socket *socket) { 754 m_io_sp.reset(socket); 755 m_uri = socket->GetRemoteConnectionURI(); 756 } 757