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 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) {
81   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION |
82                                                   LIBLLDB_LOG_OBJECT));
83   LLDB_LOGF(log, "%p ConnectionFileDescriptor::ConnectionFileDescriptor ()",
84             static_cast<void *>(this));
85 }
86 
87 ConnectionFileDescriptor::ConnectionFileDescriptor(int fd, bool owns_fd)
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 
95   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION |
96                                                   LIBLLDB_LOG_OBJECT));
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 
104 ConnectionFileDescriptor::ConnectionFileDescriptor(Socket *socket)
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 
110 ConnectionFileDescriptor::~ConnectionFileDescriptor() {
111   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION |
112                                                   LIBLLDB_LOG_OBJECT));
113   LLDB_LOGF(log, "%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()",
114             static_cast<void *>(this));
115   Disconnect(nullptr);
116   CloseCommandPipe();
117 }
118 
119 void ConnectionFileDescriptor::OpenCommandPipe() {
120   CloseCommandPipe();
121 
122   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
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 
139 void ConnectionFileDescriptor::CloseCommandPipe() {
140   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
141   LLDB_LOGF(log, "%p ConnectionFileDescriptor::CloseCommandPipe()",
142             static_cast<void *>(this));
143 
144   m_pipe.Close();
145 }
146 
147 bool ConnectionFileDescriptor::IsConnected() const {
148   return (m_read_sp && m_read_sp->IsValid()) ||
149          (m_write_sp && m_write_sp->IsValid());
150 }
151 
152 ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path,
153                                                    Status *error_ptr) {
154   std::lock_guard<std::recursive_mutex> guard(m_mutex);
155   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
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);
222             m_write_sp = m_read_sp;
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);
230           return eConnectionStatusSuccess;
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);
280       return eConnectionStatusSuccess;
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 
293 bool ConnectionFileDescriptor::InterruptRead() {
294   size_t bytes_written = 0;
295   Status result = m_pipe.Write("i", 1, bytes_written);
296   return result.Success();
297 }
298 
299 ConnectionStatus ConnectionFileDescriptor::Disconnect(Status *error_ptr) {
300   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
301   LLDB_LOGF(log, "%p ConnectionFileDescriptor::Disconnect ()",
302             static_cast<void *>(this));
303 
304   ConnectionStatus status = eConnectionStatusSuccess;
305 
306   if (!IsConnected()) {
307     LLDB_LOGF(
308         log, "%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect",
309         static_cast<void *>(this));
310     return eConnectionStatusSuccess;
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) {
363   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
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.
406     status = eConnectionStatusEndOfFile;
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.
448       status = eConnectionStatusLostConnection;
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) {
471   Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
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");
481     status = eConnectionStatusNoConnection;
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.
520       status = eConnectionStatusLostConnection;
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 
535 std::string ConnectionFileDescriptor::GetURI() { return m_uri; }
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 
552 ConnectionStatus
553 ConnectionFileDescriptor::BytesAvailable(const Timeout<std::micro> &timeout,
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 
559   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_CONNECTION));
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.
597           return eConnectionStatusLostConnection;
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:
605           return eConnectionStatusTimedOut;
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))
616           return eConnectionStatusSuccess;
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);
632             return eConnectionStatusEndOfFile;
633           case 'i':
634             // Interrupt the current read
635             return eConnectionStatusInterrupted;
636           }
637         }
638       }
639     }
640   }
641 
642   if (error_ptr)
643     error_ptr->SetErrorString("not connected");
644   return eConnectionStatusLostConnection;
645 }
646 
647 ConnectionStatus
648 ConnectionFileDescriptor::NamedSocketAccept(llvm::StringRef socket_name,
649                                             Status *error_ptr) {
650   Socket *socket = nullptr;
651   Status error =
652       Socket::UnixDomainAccept(socket_name, m_child_processes_inherit, socket);
653   if (error_ptr)
654     *error_ptr = error;
655   m_write_sp.reset(socket);
656   m_read_sp = m_write_sp;
657   if (error.Fail()) {
658     return eConnectionStatusError;
659   }
660   m_uri.assign(std::string(socket_name));
661   return eConnectionStatusSuccess;
662 }
663 
664 ConnectionStatus
665 ConnectionFileDescriptor::NamedSocketConnect(llvm::StringRef socket_name,
666                                              Status *error_ptr) {
667   Socket *socket = nullptr;
668   Status error =
669       Socket::UnixDomainConnect(socket_name, m_child_processes_inherit, socket);
670   if (error_ptr)
671     *error_ptr = error;
672   m_write_sp.reset(socket);
673   m_read_sp = m_write_sp;
674   if (error.Fail()) {
675     return eConnectionStatusError;
676   }
677   m_uri.assign(std::string(socket_name));
678   return eConnectionStatusSuccess;
679 }
680 
681 lldb::ConnectionStatus
682 ConnectionFileDescriptor::UnixAbstractSocketConnect(llvm::StringRef socket_name,
683                                                     Status *error_ptr) {
684   Socket *socket = nullptr;
685   Status error = Socket::UnixAbstractConnect(socket_name,
686                                              m_child_processes_inherit, socket);
687   if (error_ptr)
688     *error_ptr = error;
689   m_write_sp.reset(socket);
690   m_read_sp = m_write_sp;
691   if (error.Fail()) {
692     return eConnectionStatusError;
693   }
694   m_uri.assign(std::string(socket_name));
695   return eConnectionStatusSuccess;
696 }
697 
698 ConnectionStatus
699 ConnectionFileDescriptor::SocketListenAndAccept(llvm::StringRef s,
700                                                 Status *error_ptr) {
701   if (error_ptr)
702     *error_ptr = Status();
703   m_port_predicate.SetValue(0, eBroadcastNever);
704 
705   m_waiting_for_accept = true;
706   llvm::Expected<std::unique_ptr<TCPSocket>> listening_socket =
707       Socket::TcpListen(s, m_child_processes_inherit, &m_port_predicate);
708   if (!listening_socket) {
709     if (error_ptr)
710       *error_ptr = listening_socket.takeError();
711     else
712       LLDB_LOG_ERROR(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION),
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);
726   return eConnectionStatusSuccess;
727 }
728 
729 ConnectionStatus ConnectionFileDescriptor::ConnectTCP(llvm::StringRef s,
730                                                       Status *error_ptr) {
731   if (error_ptr)
732     *error_ptr = Status();
733 
734   llvm::Expected<std::unique_ptr<Socket>> socket =
735       Socket::TcpConnect(s, m_child_processes_inherit);
736   if (!socket) {
737     if (error_ptr)
738       *error_ptr = socket.takeError();
739     else
740       LLDB_LOG_ERROR(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION),
741                      socket.takeError(), "tcp connect failed: {0}");
742     return eConnectionStatusError;
743   }
744   m_write_sp = std::move(*socket);
745   m_read_sp = m_write_sp;
746   m_uri.assign(std::string(s));
747   return eConnectionStatusSuccess;
748 }
749 
750 ConnectionStatus ConnectionFileDescriptor::ConnectUDP(llvm::StringRef s,
751                                                       Status *error_ptr) {
752   if (error_ptr)
753     *error_ptr = Status();
754   llvm::Expected<std::unique_ptr<UDPSocket>> socket =
755       Socket::UdpConnect(s, m_child_processes_inherit);
756   if (!socket) {
757     if (error_ptr)
758       *error_ptr = socket.takeError();
759     else
760       LLDB_LOG_ERROR(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION),
761                      socket.takeError(), "tcp connect failed: {0}");
762     return eConnectionStatusError;
763   }
764   m_write_sp = std::move(*socket);
765   m_read_sp = m_write_sp;
766   m_uri.assign(std::string(s));
767   return eConnectionStatusSuccess;
768 }
769 
770 uint16_t
771 ConnectionFileDescriptor::GetListeningPort(const Timeout<std::micro> &timeout) {
772   auto Result = m_port_predicate.WaitForValueNotEqualTo(0, timeout);
773   return Result ? *Result : 0;
774 }
775 
776 bool ConnectionFileDescriptor::GetChildProcessesInherit() const {
777   return m_child_processes_inherit;
778 }
779 
780 void ConnectionFileDescriptor::SetChildProcessesInherit(
781     bool child_processes_inherit) {
782   m_child_processes_inherit = child_processes_inherit;
783 }
784 
785 void ConnectionFileDescriptor::InitializeSocket(Socket *socket) {
786   m_write_sp.reset(socket);
787   m_read_sp = m_write_sp;
788   m_uri = socket->GetRemoteConnectionURI();
789 }
790