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