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